├── .github ├── FUNDING.yml ├── readme │ ├── compare.png │ ├── direct.png │ ├── introduction.gif │ ├── live.png │ └── slideshow.png └── workflows │ ├── deploy-wrangler.yml │ └── run-jest.yml ├── .gitignore ├── .prettierrc.json ├── README.md ├── jest.config.js ├── package.json ├── src ├── index.ts ├── offload.ts ├── services │ ├── tiktok.ts │ └── tiktokv.ts ├── templates │ ├── index.ts │ └── pages │ │ ├── Error.tsx │ │ ├── LiveResponse.tsx │ │ ├── Message.tsx │ │ ├── VideoResponse.tsx │ │ └── WarningResponse.tsx ├── tests │ ├── photo.test.ts │ └── video.test.ts ├── types │ ├── API.ts │ ├── Live.ts │ └── Web.ts └── util │ ├── cookieHelper.ts │ ├── format.ts │ ├── generateAlternate.tsx │ ├── metaHelper.tsx │ └── responseHelper.ts ├── tsconfig.json └── wrangler.toml /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: okdargy 2 | -------------------------------------------------------------------------------- /.github/readme/compare.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/okdargy/fxTikTok/f58c13e3ff917dc392d191c5f9a9300986a9437e/.github/readme/compare.png -------------------------------------------------------------------------------- /.github/readme/direct.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/okdargy/fxTikTok/f58c13e3ff917dc392d191c5f9a9300986a9437e/.github/readme/direct.png -------------------------------------------------------------------------------- /.github/readme/introduction.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/okdargy/fxTikTok/f58c13e3ff917dc392d191c5f9a9300986a9437e/.github/readme/introduction.gif -------------------------------------------------------------------------------- /.github/readme/live.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/okdargy/fxTikTok/f58c13e3ff917dc392d191c5f9a9300986a9437e/.github/readme/live.png -------------------------------------------------------------------------------- /.github/readme/slideshow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/okdargy/fxTikTok/f58c13e3ff917dc392d191c5f9a9300986a9437e/.github/readme/slideshow.png -------------------------------------------------------------------------------- /.github/workflows/deploy-wrangler.yml: -------------------------------------------------------------------------------- 1 | name: Deploy to Cloudflare Workers 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - master 8 | - hono-rewrite 9 | 10 | jobs: 11 | deploy: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Checkout Repo 15 | uses: actions/checkout@v3 16 | - name: Install Dependencies 17 | run: npm install 18 | - name: Deploy to Cloudflare Workers 19 | uses: cloudflare/wrangler-action@v3 20 | with: 21 | apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} 22 | command: deploy src/index.ts --minify 23 | -------------------------------------------------------------------------------- /.github/workflows/run-jest.yml: -------------------------------------------------------------------------------- 1 | name: Run Unit Tests with Jest 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - master 8 | - hono-rewrite 9 | pull_request: 10 | branches: 11 | - main 12 | - master 13 | - hono-rewrite 14 | 15 | jobs: 16 | test: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: Checkout repository 20 | uses: actions/checkout@v3 21 | - name: Install pnpm 22 | run: npm install -g pnpm 23 | - name: Install dependencies 24 | run: pnpm install 25 | - name: Run Jest tests 26 | run: pnpm test 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .wrangler 4 | .env 5 | .dev.vars 6 | 7 | # Change them to your taste: 8 | package-lock.json 9 | yarn.lock 10 | pnpm-lock.yaml 11 | bun.lockb 12 | 13 | notes -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "none", 3 | "tabWidth": 2, 4 | "semi": false, 5 | "singleQuote": true, 6 | "jsxSingleQuote": true, 7 | "printWidth": 120 8 | } 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fxTikTok 2 | 3 | Embed TikTok videos and slideshows on Discord with just `s/i/n` 4 | 5 | [![Deploy to Cloudflare Workers](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/okdargy/fxtiktok) 6 | 7 | ## 📸 Screenshots 8 | 9 |
10 | Click here to preview how fxTikTok looks in action 11 | 12 | | Video Preview | 13 | | :-----------------------------------------------------------------------------------------------------------------------------------: | 14 | | Comparing `tiktok.com` vs. `tnktok.com` embeds on Discord | 15 | 16 | | Slideshow Preview | 17 | | :--------------------------------------------------------------------------------------------------------------------------: | 18 | | Slideshow embeds | 19 | 20 | | Live Preview | 21 | | :----------------------------------------------------------------------------------------------------------------: | 22 | | Live video embeds | 23 | 24 | | Direct Preview | 25 | | :-----------------------------------------------------------------------------------------------------------------------------------: | 26 | | Direct image/video support | 27 | 28 |
29 | 30 | ## 📖 Usage 31 | 32 | Using fxTikTok is easy on Discord. Fix ugly and unresponsive embeds by sending your TikTok link and then typing `s/i/n` 33 | 34 |
35 | 👁️ Visual learner? Click here to see a GIF tutorial 36 | 37 | Introduction GIF 38 |
39 | 40 | ### How does this work? 41 | 42 | When you send `s/i/n` in Discord, it modifies your most recent message using the [sed](https://www.gnu.org/software/sed/manual/sed.html) format. Specifically, it replaces the first occurrence of the second parameter (`i`) in the message with the third parameter (`n`). 43 | 44 | | Before | After | 45 | | :------------: | :------------: | 46 | | t**i**ktok.com | t**n**ktok.com | 47 | 48 | ### Using Direct Embeds 49 | 50 | Don't want all that statistic clutter on your embed and only want the video or image? Simply change your URL to `d.tnktok.com` 51 | 52 | | Before | After | 53 | | :--------------------: | :------------------: | 54 | | **www**.t**i**ktok.com | **d**.t**n**ktok.com | 55 | 56 | > Alternatively, you can also set `isDirect` to true thru the URL query by adding `?isDirect=true` at the end of your URL 57 | 58 | ### "I don't see the video's caption!" 59 | 60 | By default, we put the description into the `og:description` tag, but Discord removes that from the embed if there's a video inside the embed. We decided not to add it to the top like what [tfxktok.com](https://tfxktok.com) does to prevent the embed from getting too cluttered with hashtags. 61 | 62 | However, we want to give users the option to add it in case it brings additional context to the video. You can change your URL to `a.tnktok.com` to add the description to the top. 63 | 64 | | Before | After | 65 | | :--------------------: | :------------------: | 66 | | **www**.t**i**ktok.com | **a**.t**n**ktok.com | 67 | 68 | > Alternatively, you can also set `addDesc` to true thru the URL query by adding `?addDesc=true` at the end of your URL 69 | 70 | ### Changing to High Quality 71 | 72 | TikTok supports H.265/HEVC (High Efficiency Video Coding) which offers significantly better quality at the same file size compared to H.264, at the cost of compatibility. By default, we use H.264 quality since [many users report issues with embeds breaking with H.265](https://github.com/okdargy/fxTikTok/issues/14), but support enabling H.265. 73 | 74 | To enable high quality H.265 playback, add `?hq=true` or use `hq.tnktok.com`: 75 | | Before | After | 76 | | :--------------------: | :------------------: | 77 | | **www**.t**i**ktok.com | **hq**.t**n**ktok.com | 78 | 79 | ### Combining Modes 80 | 81 | You can combine different modes by using specific hostnames or URL query parameters. For example, if you want to enable H.265 and also see the caption, you can use `hq.a.tnktok.com` or add `?hq=true&addDesc=true` to the URL. 82 | 83 | > You cannot use Direct Mode and Caption Mode simultaneously since they contradict themselves. 84 | 85 | ### Why use tnktok.com? 86 | 87 | We check all the boxes for being one of the best TikTok embedding services with many features that others don't have. Here's a table comparing our service, tnktok.com, with the other TikTok embedding services as well as TikTok's default embeds. 88 | 89 | | | [tnktok.com](https://www.tnktok.com) | Default TikTok | [tiktxk.com](https://tiktxk.com) | [vxtiktok.com](https://vxtiktok.com) | [tfxktok.com](https://tfxktok.com) | 90 | | -------------------------------------- | ------------------------------------ | -------------- | -------------------------------- | ------------------------------------ | ---------------------------------- | 91 | | Embed playable videos | ☑️ | ☑️ | ❔ | ☑️ | ☑️ | 92 | | Embed multi-image slideshows | ☑️ | ❌ | ❔ | ❌ | ☑️ | 93 | | Embed lives | ☑️ | ➖ | ❌ | ❌ | ☑️ | 94 | | Open source | ☑️ | ❌ | ☑️ | ☑️ | ❌ | 95 | | Supports direct embeds | ☑️ | ❌ | ❌ | ❌ | ❌ | 96 | | Shows like, shares, comments | ☑️ | ☑️ | ➖ | ☑️ | ☑️ | 97 | | Removes tracking for redirects | ☑️ | ❌ | ☑️ | ☑️ | ☑️ | 98 | | Support for multi-continent short URLs | ☑️ | ☑️ | ☑️ | ☑️ | ❌ | 99 | | Support for h265/high quality | ☑️ | ❌ | ❔ | ❌ | ❌ | 100 | | Last commit | [![][tnk]][tnkc] | N/A | [![][txk]][txkc] | [![][vxt]][vxtc] | N/A | 101 | 102 | [tnk]: https://img.shields.io/github/last-commit/okdargy/fxTikTok?label 103 | [tnkc]: https://github.com/okdargy/fxTikTok/commits 104 | [txk]: https://img.shields.io/github/last-commit/Britmoji/tiktxk?label 105 | [txkc]: https://github.com/Britmoji/tiktxk/commits 106 | [vxt]: https://img.shields.io/github/last-commit/dylanpdx/vxtiktok?label 107 | [vxtc]: https://github.com/dylanpdx/vxtiktok/commits 108 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | transform: { '^.+\\.ts?$': 'ts-jest' }, 4 | testEnvironment: 'node', 5 | testRegex: '/tests/.*\\.(test|spec)?\\.(ts|tsx)$', 6 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], 7 | roots: ['/src'], 8 | moduleNameMapper: { 9 | '@/(.*)': '/src/$1' 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fxtiktok", 3 | "version": "1.0.0", 4 | "scripts": { 5 | "dev": "wrangler dev src/index.ts --env=local", 6 | "build": "wrangler build", 7 | "deploy": "wrangler deploy --minify src/index.ts", 8 | "deploy:staging": "wrangler deploy --env=staging --minify src/index.ts", 9 | "offload": "bun run src/offload.ts", 10 | "test": "jest", 11 | "prettier": "prettier . --write" 12 | }, 13 | "dependencies": { 14 | "@types/set-cookie-parser": "^2.4.7", 15 | "hono": "^3.11.7", 16 | "set-cookie-parser": "^2.6.0" 17 | }, 18 | "devDependencies": { 19 | "@cloudflare/workers-types": "^4.20230914.0", 20 | "@types/jest": "^29.5.12", 21 | "@types/react": "^18.2.46", 22 | "jest": "^29.7.0", 23 | "prettier": "3.2.5", 24 | "ts-jest": "^29.1.3", 25 | "wrangler": "^3.21.0" 26 | }, 27 | "homepage": "https://tnktok.com", 28 | "packageManager": "pnpm@8.14.1+sha512.856c4ecd97c5d3f30354ebc373cd32fb37274295c489db2d0f613a1e60f010cadfbb15036d525f3a06dec1897e4219b3c4f6d3be8f2f62fb0a366bee6aaa7533" 29 | } 30 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { Hono } from 'hono' 2 | import { scrapeLiveData, scrapeVideoData } from './services/tiktok' 3 | import { grabAwemeId } from './services/tiktok' 4 | import { VideoResponse, ErrorResponse, LiveResponse, WarningResponse } from './templates' 5 | import generateAlternate from './util/generateAlternate' 6 | import { returnHTMLResponse } from './util/responseHelper' 7 | 8 | const app = new Hono() 9 | 10 | const awemeIdPattern = /^\d{1,19}$/ 11 | const awemeLinkPattern = /\/@?([\w\d_.]*)\/(video|photo|live)\/?(\d{19})?/ 12 | 13 | // Credit: https://github.com/FixTweet/FxTwitter/blob/main/src/constants.ts#L24 14 | const BOT_REGEX = 15 | /bot|facebook|embed|got|firefox\/92|firefox\/38|curl|wget|go-http|yahoo|generator|whatsapp|revoltchat|preview|link|proxy|vkshare|images|analyzer|index|crawl|spider|python|cfnetwork|node|mastodon|http\.rb|ruby|bun\/|fiddler|iframely|steamchaturllookup/i 16 | 17 | app.get('/', () => { 18 | return new Response('', { 19 | status: 302, 20 | headers: { 21 | Location: 'https://github.com/okdargy/fxtiktok' 22 | } 23 | }) 24 | }) 25 | 26 | async function handleShort(c: any): Promise { 27 | const { videoId } = c.req.param() 28 | let id = videoId.split('.')[0] // for .mp4, .webp, etc. 29 | 30 | const res = await fetch('https://vm.tiktok.com/' + id) 31 | const link = new URL(res.url) 32 | 33 | // Clean any tracking parameters 34 | link.search = '' 35 | 36 | // If the user agent is a bot, redirect to the TikTok page 37 | if (!BOT_REGEX.test(c.req.header('User-Agent') || '')) { 38 | return new Response('', { 39 | status: 302, 40 | headers: { 41 | Location: 'https://www.tiktok.com' + link.pathname 42 | } 43 | }) 44 | } 45 | 46 | // Now, we need to check if the video is a livestream or a photo/video 47 | if (link.pathname.includes('/video') || link.pathname.includes('/photo')) { 48 | return handleVideo(c) 49 | } else if (link.pathname.includes('/live')) { 50 | return handleLive(c) 51 | } else { 52 | const responseContent = await ErrorResponse('Invalid vm link', c) 53 | return returnHTMLResponse(responseContent, 400) 54 | } 55 | } 56 | 57 | async function handleVideo(c: any): Promise { 58 | const { videoId } = c.req.param() 59 | const { addDesc, hq } = c.req.query() 60 | 61 | let id = videoId.split('.')[0] // for .mp4, .webp, etc. 62 | 63 | // If the user agent is a bot, redirect to the TikTok page 64 | if (!BOT_REGEX.test(c.req.header('User-Agent') || '')) { 65 | const url = new URL(c.req.url) 66 | 67 | // Remove tracking parameters 68 | url.search = '' 69 | 70 | return new Response('', { 71 | status: 302, 72 | headers: { 73 | Location: 'https://www.tiktok.com' + url.pathname 74 | } 75 | }) 76 | } 77 | 78 | if (!awemeIdPattern.test(id)) { 79 | const url = await grabAwemeId(id) 80 | const match = url.pathname.match(awemeLinkPattern) 81 | 82 | if (match) { 83 | id = match[3] 84 | } else { 85 | const responseContent = await ErrorResponse('Invalid video ID', c) 86 | return returnHTMLResponse(responseContent, 400) 87 | } 88 | } 89 | 90 | try { 91 | const videoInfo = await scrapeVideoData(id) 92 | 93 | if (videoInfo instanceof Error) { 94 | const responseContent = await ErrorResponse((videoInfo as Error).message, c) 95 | return returnHTMLResponse(responseContent, 500) 96 | } 97 | 98 | const url = new URL(c.req.url) 99 | const extensions = ['mp4', 'png', 'jpg', 'jpeg', 'webp', 'webm'] 100 | 101 | if ( 102 | url.hostname.includes('d.') || 103 | c.req.query('isDirect') === 'true' || 104 | extensions.some((suffix) => c.req.path.endsWith(suffix)) 105 | ) { 106 | if (videoInfo.video.duration > 0) { 107 | if ((hq || 'false').toLowerCase() == 'true' || url.hostname.includes('hq.')) { 108 | return new Response('', { 109 | status: 302, 110 | headers: { 111 | Location: 'https://fxtiktok-rewrite.dargy.workers.dev/generate/video/' + videoInfo.id + '?hq=true' 112 | } 113 | }) 114 | } else { 115 | return new Response('', { 116 | status: 302, 117 | headers: { 118 | Location: 'https://fxtiktok-rewrite.dargy.workers.dev/generate/video/' + videoInfo.id 119 | } 120 | }) 121 | } 122 | } else { 123 | return new Response('', { 124 | status: 302, 125 | headers: { 126 | Location: 'https://fxtiktok-rewrite.dargy.workers.dev/generate/image/' + videoInfo.id 127 | } 128 | }) 129 | } 130 | } else { 131 | if (videoInfo.isContentClassified === true) { 132 | const responseContent = await WarningResponse('Sensitive Content', 'the video being age-restricted', c) 133 | return returnHTMLResponse(responseContent, 200) 134 | } 135 | 136 | const responseContent = await VideoResponse( 137 | videoInfo, 138 | (addDesc || 'false').toLowerCase() == 'true' || url.hostname.includes('a.'), 139 | (hq || 'false').toLowerCase() == 'true' || url.hostname.includes('hq.'), 140 | c 141 | ) 142 | return returnHTMLResponse(responseContent) 143 | } 144 | } catch (e) { 145 | const responseContent = await ErrorResponse((e as Error).message, c) 146 | return returnHTMLResponse(responseContent, 500) 147 | } 148 | } 149 | 150 | async function handleLive(c: any): Promise { 151 | const { author, videoId } = c.req.param() 152 | let authorName = author 153 | 154 | // If the user agent is a bot, redirect to the TikTok page 155 | if (!BOT_REGEX.test(c.req.header('User-Agent') || '')) { 156 | const url = new URL(c.req.url) 157 | 158 | // Remove tracking parameters 159 | url.search = '' 160 | 161 | return new Response('', { 162 | status: 302, 163 | headers: { 164 | Location: 'https://www.tiktok.com' + url.pathname 165 | } 166 | }) 167 | } 168 | 169 | if (!author && !awemeIdPattern.test(videoId)) { 170 | const url = await grabAwemeId(videoId) 171 | const match = url.pathname.match(awemeLinkPattern) 172 | 173 | if (match) { 174 | authorName = match[1] 175 | } else { 176 | const responseContent = await ErrorResponse('Invalid live ID', c) 177 | return returnHTMLResponse(responseContent, 400) 178 | } 179 | } 180 | 181 | authorName = authorName.startsWith('@') ? authorName.substring(1) : authorName 182 | 183 | try { 184 | const liveData = await scrapeLiveData(authorName) 185 | 186 | if (liveData instanceof Error) { 187 | const responseContent = await ErrorResponse((liveData as Error).message, c) 188 | return returnHTMLResponse(responseContent, 500) 189 | } 190 | 191 | const responseContent = await LiveResponse(liveData, c) 192 | return returnHTMLResponse(responseContent) 193 | } catch (e) { 194 | const responseContent = await ErrorResponse((e as Error).message, c) 195 | return returnHTMLResponse(responseContent, 500) 196 | } 197 | } 198 | 199 | app.get('/generate/alternate', (c) => { 200 | const content = JSON.stringify(generateAlternate(c)) 201 | return new Response(content, { 202 | status: 200, 203 | headers: { 204 | 'Content-Type': 'application/json; charset=utf-8', 205 | 'Cache-Control': 'public, max-age=3600' 206 | } 207 | }) 208 | }) 209 | 210 | app.get('/generate/video/:videoId', async (c) => { 211 | const { videoId } = c.req.param() 212 | const hq = c.req.query('hq') === 'true' || c.req.query('quality') === 'hq' 213 | 214 | try { 215 | // To ensure the video is valid, decrease load on TikWM by checking the video data first 216 | const data = await scrapeVideoData(videoId) 217 | 218 | if (data instanceof Error) { 219 | return new Response((data as Error).message, { 220 | status: 500, 221 | headers: { 222 | 'Cache-Control': 'no-cache, no-store, must-revalidate' 223 | } 224 | }) 225 | } 226 | 227 | const highAvailable = data.video.bitrateInfo.find((bitrate) => bitrate.CodecType.includes('h265')) 228 | 229 | if (hq && highAvailable) { 230 | return c.redirect(`https://tikwm.com/video/media/hdplay/${videoId}.mp4`) 231 | } else { 232 | return c.redirect(`https://tikwm.com/video/media/play/${videoId}.mp4`) 233 | } 234 | } catch (e) { 235 | return new Response((e as Error).message, { 236 | status: 500, 237 | headers: { 238 | 'Cache-Control': 'no-cache, no-store, must-revalidate' 239 | } 240 | }) 241 | } 242 | }) 243 | 244 | app.get('/generate/image/:videoId', async (c) => { 245 | const { videoId } = c.req.param() 246 | const index = c.req.query('index') || 0 247 | 248 | if (!videoId) return new Response('Missing video ID', { status: 400 }) 249 | if (!awemeIdPattern.test(videoId)) return new Response('Invalid video ID', { status: 400 }) 250 | if (isNaN(Number(index))) return new Response('Invalid image index', { status: 400 }) 251 | 252 | try { 253 | const data = await scrapeVideoData(videoId) 254 | 255 | if ('imagePost' in data && data.imagePost.images.length > 0 && +index < data.imagePost.images.length) { 256 | return c.redirect(data.imagePost.images[+index].imageURL.urlList[0]) 257 | } else { 258 | throw new Error('Image not found') 259 | } 260 | } catch (e) { 261 | return new Response((e as Error).message, { 262 | status: 500, 263 | headers: { 264 | 'Cache-Control': 'no-cache, no-store, must-revalidate' 265 | } 266 | }) 267 | } 268 | }) 269 | 270 | app.get('/generate/image/:videoId/:imageCount', async (c) => { 271 | const { videoId, imageCount } = c.req.param() 272 | 273 | if (!videoId) return new Response('Missing video ID', { status: 400 }) 274 | if (!awemeIdPattern.test(videoId)) return new Response('Invalid video ID', { status: 400 }) 275 | 276 | if (isNaN(Number(imageCount)) || parseInt(imageCount) < 1) return new Response('Invalid image count', { status: 400 }) 277 | const imageIndex = parseInt(imageCount) - 1 // 0-indexed 278 | 279 | try { 280 | const data = await scrapeVideoData(videoId) 281 | 282 | if (data instanceof Error) { 283 | return new Response((data as Error).message, { 284 | status: 500, 285 | headers: { 286 | 'Cache-Control': 'no-cache, no-store, must-revalidate' 287 | } 288 | }) 289 | } 290 | 291 | const images = await fetch('https://tikwm.com/api/', { 292 | headers: { 293 | Accept: 'application/json, text/javascript, */*; q=0.01', 294 | 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' 295 | }, 296 | body: 'url=' + videoId + '&count=12&cursor=0&web=1&hd=1', 297 | method: 'POST' 298 | }) 299 | 300 | const imageJson = (await images.json()) as { data: { images: string[] } } 301 | if (!imageJson.data.images[imageIndex]) return new Response('Image not found', { status: 404 }) 302 | 303 | return c.redirect(imageJson.data.images[imageIndex]) 304 | } catch (e) { 305 | return new Response((e as Error).message, { 306 | status: 500, 307 | headers: { 308 | 'Cache-Control': 'no-cache, no-store, must-revalidate' 309 | } 310 | }) 311 | } 312 | }) 313 | 314 | app.get('/generate/livePic/:author', async (c) => { 315 | const { author } = c.req.param() 316 | 317 | try { 318 | const data = await scrapeLiveData(author) 319 | 320 | if (data instanceof Error) { 321 | return new Response((data as Error).message, { 322 | status: 500, 323 | headers: { 324 | 'Cache-Control': 'no-cache, no-store, must-revalidate' 325 | } 326 | }) 327 | } 328 | 329 | return c.redirect(data.liveRoomUserInfo.user.avatarLarger) 330 | } catch (e) { 331 | return new Response((e as Error).message, { 332 | status: 500, 333 | headers: { 334 | 'Cache-Control': 'no-cache, no-store, must-revalidate' 335 | } 336 | }) 337 | } 338 | }) 339 | 340 | const routes = [ 341 | { 342 | path: '/:videoId', 343 | handler: handleShort 344 | }, 345 | { 346 | path: '/t/:videoId', 347 | handler: handleShort 348 | }, 349 | { 350 | path: '/*/video/:videoId', 351 | handler: handleVideo 352 | }, 353 | { 354 | path: '/*/photo/:videoId', 355 | handler: handleVideo 356 | }, 357 | { 358 | path: '/:author/live', 359 | handler: handleLive 360 | } 361 | ] 362 | 363 | // temp-fix: add trailing slash to all routes 364 | routes.forEach((route) => { 365 | app.get(route.path, route.handler) 366 | app.get(route.path + '/', route.handler) 367 | }) 368 | 369 | export default app 370 | -------------------------------------------------------------------------------- /src/offload.ts: -------------------------------------------------------------------------------- 1 | import { Hono } from 'hono' 2 | import generateAlternate from './util/generateAlternate' 3 | 4 | const app = new Hono() 5 | 6 | app.get('/', () => { 7 | return new Response(JSON.stringify({ 8 | message: "fxTikTok offload server is running!", 9 | github: "https://github.com/okdargy/fxTikTok", 10 | }), { 11 | status: 200, 12 | headers: { 13 | 'Content-Type': 'application/json; charset=utf-8', 14 | 'Cache-Control': 'public, max-age=3600' 15 | } 16 | }) 17 | }) 18 | 19 | app.get('/generate/alternate', (c) => { 20 | const content = JSON.stringify(generateAlternate(c)) 21 | 22 | return new Response(content, { 23 | status: 200, 24 | headers: { 25 | 'Content-Type': 'application/json; charset=utf-8', 26 | 'Cache-Control': 'public, max-age=3600' 27 | } 28 | }) 29 | }) 30 | 31 | export default { 32 | port: 8787, 33 | fetch: app.fetch, 34 | } 35 | 36 | console.log('fxTikTok offload server is running on port 8787') -------------------------------------------------------------------------------- /src/services/tiktok.ts: -------------------------------------------------------------------------------- 1 | import { WebJSONResponse, ItemStruct } from '../types/Web' 2 | import { LiveWebJSONResponse, LiveRoom } from '../types/Live' 3 | import Cookie from '../util/cookieHelper' 4 | import cookieParser from 'set-cookie-parser' 5 | 6 | const cookie = new Cookie([]) 7 | 8 | export async function grabAwemeId(videoId: string): Promise { 9 | const res = await fetch('https://vm.tiktok.com/' + videoId) 10 | return new URL(res.url) 11 | } 12 | 13 | export async function scrapeVideoData(awemeId: string, author?: string): Promise { 14 | const res = await fetch(`https://www.tiktok.com/@${author || 'i'}/video/${awemeId}`, { 15 | method: 'GET', 16 | headers: { 17 | Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8', 18 | 'User-Agent': 19 | 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36', 20 | Cookie: cookie.getCookiesAsString() 21 | }, 22 | cf: { 23 | cacheEverything: false, 24 | cacheTtlByStatus: { '200-299': 86400, 404: 1, '500-599': 0 } 25 | } 26 | }) 27 | 28 | let cookies = cookieParser(res.headers.get('set-cookie')!) 29 | cookie.setCookies(cookies) 30 | 31 | const html = await res.text() 32 | 33 | try { 34 | const resJson = html 35 | .split('')[0] 37 | const json: WebJSONResponse = JSON.parse(resJson) 38 | 39 | if ( 40 | !json['__DEFAULT_SCOPE__']['webapp.video-detail'] || 41 | json['__DEFAULT_SCOPE__']['webapp.video-detail'].statusCode == 10204 42 | ) 43 | throw new Error('Could not find video data') 44 | 45 | const videoInfo = json['__DEFAULT_SCOPE__']['webapp.video-detail']['itemInfo']['itemStruct'] 46 | 47 | return videoInfo 48 | } catch (err) { 49 | throw new Error('Could not parse video info') 50 | } 51 | } 52 | 53 | export async function scrapeLiveData(author: string): Promise { 54 | const res = await fetch(`https://www.tiktok.com/@${author}/live`, { 55 | method: 'GET', 56 | headers: { 57 | Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8', 58 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:126.0) Gecko/20100101 Firefox/126.0', 59 | Cookie: cookie.getCookiesAsString() 60 | } 61 | }) 62 | 63 | let cookies = cookieParser(res.headers.get('set-cookie')!) 64 | cookie.setCookies(cookies) 65 | 66 | const html = await res.text() 67 | 68 | try { 69 | const resJson = html.split('')[0] 70 | const json: LiveWebJSONResponse = JSON.parse(resJson) 71 | 72 | if (!json['LiveRoom']) throw new Error('Could not find live data') 73 | 74 | return json['LiveRoom'] 75 | } catch (err) { 76 | throw new Error('Could not parse live data') 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/services/tiktokv.ts: -------------------------------------------------------------------------------- 1 | import { TikTokAPIResponse, AwemeList } from '../types/API' 2 | 3 | export async function getVideoInfo(awemeId: string): Promise { 4 | const apiUrl = new URL('https://api22-normal-c-alisg.tiktokv.com/aweme/v1/feed/') 5 | 6 | apiUrl.search = new URLSearchParams({ 7 | region: 'US', 8 | carrier_region: 'US', 9 | aweme_id: awemeId, 10 | iid: '7318518857994389254', 11 | device_id: '7318517321748022790', 12 | channel: 'googleplay', 13 | app_name: 'musical_ly', 14 | version_code: '300904', 15 | device_platform: 'android', 16 | device_type: 'ASUS_Z01QD', 17 | os_version: '9' 18 | }).toString() 19 | 20 | const res: Response = await fetch(apiUrl.toString(), { 21 | headers: { 22 | 'User-Agent': 23 | 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Mobile Safari/537.36' 24 | }, 25 | cf: { 26 | cacheEverything: true, 27 | cacheTtlByStatus: { '200-299': 86400, 404: 1, '500-599': 0 } 28 | } 29 | }) 30 | const json = (await res.json()) as TikTokAPIResponse 31 | const videoInfo: AwemeList | undefined = json.aweme_list.find((aweme) => aweme.aweme_id === awemeId) 32 | 33 | if (videoInfo) { 34 | return videoInfo 35 | } else { 36 | return new Error('Could not find video info') 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/templates/index.ts: -------------------------------------------------------------------------------- 1 | export * from './pages/VideoResponse' 2 | export * from './pages/Error' 3 | export * from './pages/LiveResponse' 4 | export * from './pages/WarningResponse' 5 | export * from './pages/Message' 6 | -------------------------------------------------------------------------------- /src/templates/pages/Error.tsx: -------------------------------------------------------------------------------- 1 | import { Context } from 'hono' 2 | import MetaHelper from '../../util/metaHelper' 3 | 4 | export function ErrorResponse(error: string, c: Context): JSX.Element { 5 | return ( 6 | <> 7 | {MetaHelper(c, [ 8 | { 9 | name: 'og:title', 10 | content: `❌ ${error}` 11 | }, 12 | { 13 | name: 'theme-color', 14 | content: '#dd2e44' 15 | }, 16 | { 17 | name: 'og:description', 18 | content: 'An error occurred while trying to fetch data. Please try again later.' 19 | }, 20 | { 21 | name: 'og:site_name', 22 | content: 'fxTikTok' 23 | } 24 | ])} 25 | 26 | ) 27 | } 28 | -------------------------------------------------------------------------------- /src/templates/pages/LiveResponse.tsx: -------------------------------------------------------------------------------- 1 | import { Context } from 'hono' 2 | import MetaHelper from '@/util/metaHelper' 3 | import { LiveRoom } from '@/types/Live' 4 | import { formatNumber, formatTime } from '@/util/format' 5 | 6 | export function LiveResponse(data: LiveRoom, c: Context): JSX.Element { 7 | let title = '' 8 | 9 | title += `👀 ${formatNumber(String(data.liveRoomUserInfo.liveRoom.liveRoomStats.userCount))} ` 10 | 11 | if (data.liveRoomUserInfo.liveRoom.status !== 4) { 12 | // live has NOT ended 13 | title += `🕒 ${formatTime(data.liveRoomUserInfo.liveRoom.startTime)} ` 14 | } else { 15 | title += `⌛ ENDED ` 16 | } 17 | 18 | return ( 19 | <> 20 | {MetaHelper(c, 21 | [ 22 | { 23 | name: 'og:title', 24 | content: title.trim() 25 | }, 26 | { 27 | name: 'theme-color', 28 | content: '#ff0050' 29 | }, 30 | { 31 | name: 'twitter:site', 32 | content: `@${data.liveRoomUserInfo.user.uniqueId}` // @username 33 | }, 34 | { 35 | name: 'twitter:creator', 36 | content: `@${data.liveRoomUserInfo.user.uniqueId}` // @username 37 | }, 38 | { 39 | name: 'twitter:title', 40 | content: `${data.liveRoomUserInfo.user.nickname} (@${data.liveRoomUserInfo.user.nickname})` // Nickname (@username) 41 | }, 42 | { 43 | name: 'og:url', 44 | content: `https://www.tiktok.com/@${data.liveRoomUserInfo.user.uniqueId}/live` 45 | }, 46 | { 47 | name: 'og:description', 48 | content: data.liveRoomUserInfo.liveRoom.title 49 | }, 50 | { 51 | name: 'og:image', 52 | content: 53 | 'https://fxtiktok-rewrite.dargy.workers.dev/generate/livePic/' + data.liveRoomUserInfo.user.uniqueId 54 | }, 55 | { 56 | name: 'og:image:type', 57 | content: 'image/jpeg' 58 | }, 59 | { 60 | name: 'og:type', 61 | content: 'image.other' 62 | }, 63 | { 64 | name: 'twitter:card', 65 | content: 'summary_large_image' 66 | } 67 | ], 68 | { 69 | unique_id: data.liveRoomUserInfo.user.uniqueId, 70 | nickname: data.liveRoomUserInfo.user.nickname 71 | } 72 | )} 73 | 74 | ) 75 | } 76 | -------------------------------------------------------------------------------- /src/templates/pages/Message.tsx: -------------------------------------------------------------------------------- 1 | import { Context } from 'hono' 2 | import MetaHelper from '../../util/metaHelper' 3 | 4 | export function MessageResponse(title: string, message: string, c: Context): JSX.Element { 5 | return ( 6 | <> 7 | {MetaHelper(c, [ 8 | { 9 | name: 'og:title', 10 | content: title 11 | }, 12 | { 13 | name: 'theme-color', 14 | content: '#ff0050' 15 | }, 16 | { 17 | name: 'og:description', 18 | content: message 19 | } 20 | ])} 21 | 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /src/templates/pages/VideoResponse.tsx: -------------------------------------------------------------------------------- 1 | import MetaHelper from '../../util/metaHelper' 2 | import { ItemStruct } from '../../types/Web' 3 | import { formatNumber } from '../../util/format' 4 | import { Buffer } from 'node:buffer' 5 | import { Context } from 'hono' 6 | 7 | export function VideoResponse(data: ItemStruct, addDesc: Boolean, hq: boolean, c: Context): JSX.Element { 8 | let videoUrl = 'https://fxtiktok-rewrite.dargy.workers.dev/generate/video/' + data.id + (hq ? '?hq=true' : '') 9 | let videoMeta: { name: string; content: string }[] = [] 10 | 11 | if (data.video.duration !== 0) { 12 | videoMeta = [ 13 | { 14 | name: 'og:video', 15 | content: videoUrl 16 | }, 17 | { 18 | name: 'og:video:secure_url', 19 | content: videoUrl 20 | }, 21 | { 22 | name: 'og:video:type', 23 | content: 'video/mp4' 24 | }, 25 | { 26 | name: 'og:video:width', 27 | content: data.video.width.toString() 28 | }, 29 | { 30 | name: 'og:video:height', 31 | content: data.video.height.toString() 32 | }, 33 | { 34 | name: 'og:type', 35 | content: 'video' 36 | }, 37 | { 38 | name: 'og:video:type', 39 | content: 'video/mp4' 40 | }, 41 | 42 | { 43 | name: 'twitter:card', 44 | content: 'player' 45 | }, 46 | { 47 | name: 'twitter:player:height', 48 | content: data.video.height.toString() 49 | }, 50 | { 51 | name: 'twitter:player:width', 52 | content: data.video.width.toString() 53 | }, 54 | { 55 | name: 'twitter:player', 56 | content: videoUrl 57 | }, 58 | { 59 | name: 'twitter:player:stream', 60 | content: videoUrl 61 | }, 62 | { 63 | name: 'twitter:player:stream:content_type', 64 | content: 'video/mp4' 65 | } 66 | ] 67 | } else { 68 | const numberOfImages = data.imagePost.images.length > 4 ? 4 : data.imagePost.images.length 69 | 70 | for (let i = 0; i < numberOfImages; i++) { 71 | videoMeta = [ 72 | ...videoMeta, 73 | { 74 | name: 'og:image', 75 | content: 'https://fxtiktok-rewrite.dargy.workers.dev/generate/image/' + data.id + '?index=' + i 76 | }, 77 | { 78 | name: 'og:image:type', 79 | content: 'image/jpeg' 80 | }, 81 | { 82 | name: 'og:image:width', 83 | content: 'auto' 84 | }, 85 | { 86 | name: 'og:image:height', 87 | content: 'auto' 88 | }, 89 | { 90 | name: 'og:type', 91 | content: 'image.other' 92 | }, 93 | { 94 | name: 'twitter:card', 95 | content: 'summary_large_image' 96 | } 97 | ] 98 | } 99 | } 100 | 101 | let title = '' 102 | 103 | title += `❤️ ${formatNumber(data.stats.diggCount.toString())} ` 104 | title += `💬 ${formatNumber(data.stats.commentCount.toString())} ` 105 | title += `🔁 ${formatNumber(data.stats.shareCount.toString())} ` 106 | 107 | if (data.imagePost) { 108 | title += `🖼️ ${data.imagePost.images.length.toString()} ` 109 | } 110 | 111 | return ( 112 | <> 113 | {MetaHelper(c, 114 | [ 115 | { 116 | name: 'og:title', 117 | content: title.trim() 118 | }, 119 | { 120 | name: 'theme-color', 121 | content: '#ff0050' // TikTok's theme color 122 | }, 123 | { 124 | name: 'twitter:site', 125 | content: `@${data.author.uniqueId}` // @username 126 | }, 127 | { 128 | name: 'twitter:creator', 129 | content: `@${data.author.uniqueId}` // @username 130 | }, 131 | { 132 | name: 'twitter:title', 133 | content: `${data.author.nickname} (@${data.author.uniqueId})` // Nickname (@username) 134 | }, 135 | { 136 | name: 'og:url', 137 | content: `https://www.tiktok.com/@${data.author.uniqueId}/video/${data.id}` 138 | }, 139 | ...(!addDesc 140 | ? [ 141 | { 142 | name: 'og:description', 143 | content: data.desc 144 | } 145 | ] 146 | : []), 147 | ...videoMeta 148 | ], 149 | { 150 | unique_id: data.author.uniqueId, 151 | nickname: data.author.nickname, 152 | ...(addDesc ? { description: Buffer.from(data.desc).toString('base64') } : {}) 153 | } 154 | )} 155 | 156 | ) 157 | } 158 | -------------------------------------------------------------------------------- /src/templates/pages/WarningResponse.tsx: -------------------------------------------------------------------------------- 1 | import { Context } from 'hono' 2 | import MetaHelper from '../../util/metaHelper' 3 | 4 | export function WarningResponse(title: string, reason: string, c: Context): JSX.Element { 5 | return ( 6 | <> 7 | {MetaHelper(c, [ 8 | { 9 | name: 'og:title', 10 | content: `⚠️ ${title}` 11 | }, 12 | { 13 | name: 'theme-color', 14 | content: '#f7c500' 15 | }, 16 | { 17 | name: 'og:description', 18 | content: `Sorry, we were unable to show this video due to ${reason}. If you would like to view the video, please visit TikTok directly.` 19 | } 20 | ])} 21 | 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /src/tests/photo.test.ts: -------------------------------------------------------------------------------- 1 | import app from '@/index' 2 | 3 | describe('GET /@i/photo/:videoId', () => { 4 | it('should return 200', async () => { 5 | const res = await app.request('/@i/photo/7335753580093164833', { 6 | method: 'GET', 7 | headers: { 8 | 'User-Agent': 'Mozilla/5.0 (compatible; Discordbot/2.0; +https://discordapp.com)' 9 | } 10 | }) 11 | 12 | expect(res.status).toBe(200) 13 | }) 14 | 15 | // no discord user agent, redirects 16 | it('should return 302', async () => { 17 | const res = await app.request('/@i/photo/7335753580093164833', { 18 | method: 'GET' 19 | }) 20 | 21 | expect(res.status).toBe(302) 22 | }) 23 | 24 | it('should return 500', async () => { 25 | const res = await app.request('/@i/photo/123', { 26 | method: 'GET', 27 | headers: { 28 | 'User-Agent': 'Mozilla/5.0 (compatible; Discordbot/2.0; +https://discordapp.com)' 29 | } 30 | }) 31 | 32 | expect(res.status).toBe(500) 33 | expect(await res.text()).toContain('An error occurred while trying to fetch data. Please try again later.') 34 | }) 35 | }) 36 | 37 | describe('GET /generate/image/:videoId', () => { 38 | it('should return 302', async () => { 39 | const res = await app.request('/generate/image/7335753580093164833', { 40 | method: 'GET' 41 | }) 42 | 43 | expect(res.status).toBe(302) 44 | }) 45 | 46 | it('should return 500', async () => { 47 | const res = await app.request('/generate/image/123', { 48 | method: 'GET' 49 | }) 50 | 51 | expect(res.status).toBe(500) 52 | }) 53 | }) 54 | -------------------------------------------------------------------------------- /src/tests/video.test.ts: -------------------------------------------------------------------------------- 1 | import app from '@/index' 2 | 3 | describe('GET /@i/video/:videoId', () => { 4 | it('should return 200', async () => { 5 | const res = await app.request('/@pr4yforgabs/video/7332187682480590112', { 6 | method: 'GET', 7 | headers: { 8 | 'User-Agent': 'Mozilla/5.0 (compatible; Discordbot/2.0; +https://discordapp.com)' 9 | } 10 | }) 11 | 12 | expect(res.status).toBe(200) 13 | }) 14 | 15 | it('should return 200 (h.265)', async () => { 16 | const res = await app.request('/@pr4yforgabs/video/7332187682480590112?hq=true', { 17 | method: 'GET', 18 | headers: { 19 | 'User-Agent': 'Mozilla/5.0 (compatible; Discordbot/2.0; +https://discordapp.com)' 20 | } 21 | }) 22 | 23 | expect(res.status).toBe(200) 24 | expect(await res.text()).toContain('?hq=true') 25 | }) 26 | 27 | it('should return 200 (description)', async () => { 28 | const res = await app.request('/@pr4yforgabs/video/7332187682480590112?addDesc=true', { 29 | method: 'GET', 30 | headers: { 31 | 'User-Agent': 'Mozilla/5.0 (compatible; Discordbot/2.0; +https://discordapp.com)' 32 | } 33 | }) 34 | 35 | expect(res.status).toBe(200) 36 | expect(await res.text()).toContain('description=') 37 | }) 38 | 39 | // no discord user agent, redirects 40 | it('should return 302', async () => { 41 | const res = await app.request('/@pr4yforgabs/video/7332187682480590112', { 42 | method: 'GET' 43 | }) 44 | 45 | expect(res.status).toBe(302) 46 | }) 47 | 48 | it('should return 500', async () => { 49 | const res = await app.request('/@i/video/123', { 50 | method: 'GET', 51 | headers: { 52 | 'User-Agent': 'Mozilla/5.0 (compatible; Discordbot/2.0; +https://discordapp.com)' 53 | } 54 | }) 55 | 56 | expect(res.status).toBe(500) 57 | expect(await res.text()).toContain('An error occurred while trying to fetch data. Please try again later.') 58 | }) 59 | }) 60 | 61 | describe('GET /@i/video/:videoId (age restricted)', () => { 62 | // /t/ZP81NmQk9/ 63 | it('should return 200', async () => { 64 | const res = await app.request('/t/ZP81NmQk9', { 65 | method: 'GET', 66 | headers: { 67 | 'User-Agent': 'Mozilla/5.0 (compatible; Discordbot/2.0; +https://discordapp.com)' 68 | } 69 | }) 70 | 71 | expect(res.status).toBe(200) 72 | expect(await res.text()).toContain('⚠️') 73 | }) 74 | }) 75 | 76 | describe('GET /t/:videoId', () => { 77 | it('should return 200', async () => { 78 | const res = await app.request('/t/ZPRKrbUB1', { 79 | method: 'GET', 80 | headers: { 81 | 'User-Agent': 'Mozilla/5.0 (compatible; Discordbot/2.0; +https://discordapp.com)' 82 | } 83 | }) 84 | 85 | expect(res.status).toBe(200) 86 | }) 87 | }) 88 | 89 | describe('GET /generate/video/:videoId', () => { 90 | it('should return 302', async () => { 91 | const res = await app.request('/generate/video/7332187682480590112', { 92 | method: 'GET' 93 | }) 94 | 95 | expect(res.status).toBe(302) 96 | }) 97 | 98 | it('should return 302 (h.265)', async () => { 99 | const res = await app.request('/generate/video/7332187682480590112?hq=true', { 100 | method: 'GET' 101 | }) 102 | 103 | expect(res.status).toBe(302) 104 | expect(res.headers.get('Location')).toContain('hdplay') 105 | }) 106 | 107 | it('should return 500', async () => { 108 | const res = await app.request('/generate/video/123', { 109 | method: 'GET' 110 | }) 111 | 112 | expect(res.status).toBe(500) 113 | }) 114 | }) 115 | 116 | describe('GET /generate/alternate', () => { 117 | it('should return 200 (English)', async () => { 118 | const res = await app.request('/generate/alternate?description=I2Z5ICNmb3J5b3UgI3N0cmF3YmVycnkgI2Nob2NvbGF0ZSAjY2hvY29sYXRlY292ZXJlZHN0cmF3YmVycmllcyA%253D', { 119 | method: 'GET' 120 | }) 121 | 122 | expect(res.status).toBe(200) 123 | const jsonResponse = await res.json() as { provider_name: string }; 124 | expect(jsonResponse.provider_name).toEqual('#fy #foryou #strawberry #chocolate #chocolatecoveredstrawberries ') 125 | }) 126 | 127 | it('should return 200 (Russian)', async () => { 128 | const res = await app.request('/generate/alternate?description=0JXRgdGC0Ywg0LIg0LrQvtC80LzQtdC90YLQsNGA0LjRj9GFINC%252F0LXRgNC10LLQvtC00YfQuNC60Lgg0YEg0Y%252FQt9GL0LrQsCDQv9GA0LjRiNC10LvRjNGG0LXQsj8g8J%252BRvSDwn5O5OiBhcmllbGlwaWxsbw%253D%253D', { 129 | method: 'GET' 130 | }) 131 | 132 | expect(res.status).toBe(200) 133 | const jsonResponse = await res.json() as { provider_name: string }; 134 | expect(jsonResponse.provider_name).toEqual('Есть в комментариях переводчики с языка пришельцев? 👽 📹: arielipillo') 135 | }) 136 | }) -------------------------------------------------------------------------------- /src/types/API.ts: -------------------------------------------------------------------------------- 1 | export interface ServiceTikTokResponse { 2 | success: boolean 3 | data: AwemeList 4 | } 5 | 6 | export interface TikTokAPIResponse { 7 | status_code: number 8 | min_cursor: number 9 | max_cursor: number 10 | has_more: number 11 | aweme_list: AwemeList[] 12 | home_model: number 13 | refresh_clear: number 14 | extra: ExtraClass 15 | log_pb: LogPb 16 | preload_ads: any[] 17 | preload_awemes: null 18 | log_info: TikTokAPIResponseLogInfo 19 | } 20 | 21 | export interface AwemeList { 22 | aweme_id: string 23 | desc: string 24 | create_time: number 25 | author: AwemeListAuthor 26 | music: AddedSoundMusicInfo 27 | cha_list: ChaList[] | null 28 | video: Video 29 | share_url: string 30 | user_digged: number 31 | statistics: Statistics 32 | status: Status 33 | rate: number 34 | text_extra: Extra[] 35 | is_top: number 36 | label_top: LabelTop 37 | share_info: ChaListShareInfo 38 | distance: string 39 | video_labels: any[] 40 | is_vr: boolean 41 | is_ads: boolean 42 | duration: number 43 | aweme_type: number 44 | cmt_swt: boolean 45 | image_infos: null 46 | risk_infos: RiskInfos 47 | is_relieve: boolean 48 | sort_label: string 49 | position: null 50 | uniqid_position: null 51 | author_user_id: number 52 | bodydance_score: number 53 | geofencing: any[] 54 | is_hash_tag: number 55 | is_pgcshow: boolean 56 | region: string 57 | video_text: any[] 58 | collect_stat: number 59 | label_top_text: null 60 | group_id: string 61 | prevent_download: boolean 62 | nickname_position: null 63 | challenge_position: null 64 | item_comment_settings: number 65 | with_promotional_music: boolean 66 | long_video: null 67 | item_duet: number 68 | item_react: number 69 | desc_language: string 70 | interaction_stickers: InteractionSticker[] | null 71 | misc_info: string 72 | origin_comment_ids: null 73 | commerce_config_data: null 74 | distribute_type: number 75 | video_control: VideoControl 76 | commerce_info: CommerceInfo 77 | anchors: null 78 | hybrid_label: null 79 | with_survey: boolean 80 | geofencing_regions: null 81 | cover_labels: null 82 | mask_infos: any[] 83 | search_highlight: null 84 | playlist_blocked: boolean 85 | green_screen_materials: null 86 | interact_permission: InteractPermission 87 | question_list: null 88 | interaction_tag_info?: InteractionTagInfo 89 | content_desc: string 90 | content_desc_extra: Extra[] 91 | products_info: null 92 | follow_up_publish_from_id: number 93 | disable_search_trending_bar: boolean 94 | image_post_info?: ImagePostInfo 95 | music_begin_time_in_ms: number 96 | music_end_time_in_ms?: number 97 | item_distribute_source: string 98 | item_source_category: number 99 | branded_content_accounts: null 100 | is_description_translatable: boolean 101 | follow_up_item_id_groups: string 102 | is_text_sticker_translatable: boolean 103 | text_sticker_major_lang: string 104 | original_client_text: OriginalClientText 105 | music_selected_from: string 106 | tts_voice_ids: null 107 | reference_tts_voice_ids: null 108 | voice_filter_ids: null 109 | reference_voice_filter_ids: null 110 | music_title_style: number 111 | animated_image_info: AnimatedImageInfo 112 | comment_config: CommentConfig 113 | added_sound_music_info: AddedSoundMusicInfo 114 | origin_volume: string 115 | music_volume: string 116 | support_danmaku: boolean 117 | has_danmaku: boolean 118 | muf_comment_info_v2: null 119 | behind_the_song_music_ids: null 120 | behind_the_song_video_music_ids: null 121 | content_original_type: number 122 | shoot_tab_name?: string 123 | content_type?: string 124 | content_size_type?: number 125 | operator_boost_info: null 126 | log_info: AwemeListLogInfo 127 | main_arch_common: string 128 | aigc_info: AigcInfo 129 | banners: null 130 | picked_users: null 131 | comment_topbar_info: null 132 | batch_index?: number 133 | } 134 | 135 | export interface AddedSoundMusicInfo { 136 | id: number 137 | id_str: string 138 | title: string 139 | author: string 140 | album: string 141 | cover_large: LabelTop 142 | cover_medium: LabelTop 143 | cover_thumb: LabelTop 144 | play_url: LabelTop 145 | source_platform: number 146 | duration: number 147 | extra: string 148 | user_count: number 149 | position: null 150 | collect_stat: number 151 | status: number 152 | offline_desc: string 153 | owner_id: string 154 | owner_nickname: string 155 | is_original: boolean 156 | mid: string 157 | binded_challenge_id: number 158 | author_deleted: boolean 159 | owner_handle: string 160 | author_position: null 161 | prevent_download: boolean 162 | strong_beat_url?: LabelTop 163 | external_song_info: any[] 164 | sec_uid: string 165 | avatar_thumb: LabelTop 166 | avatar_medium: LabelTop 167 | preview_start_time: number 168 | preview_end_time: number 169 | is_commerce_music: boolean 170 | is_original_sound: boolean 171 | artists: null 172 | lyric_short_position: null 173 | mute_share: boolean 174 | tag_list: null 175 | is_author_artist: boolean 176 | is_pgc: boolean 177 | search_highlight: null 178 | multi_bit_rate_play_info: null 179 | tt_to_dsp_song_infos: null 180 | recommend_status: number 181 | } 182 | 183 | export interface LabelTop { 184 | uri: string 185 | url_list: string[] 186 | width: number 187 | height: number 188 | url_prefix: null 189 | data_size?: number 190 | url_key?: string 191 | file_hash?: string 192 | } 193 | 194 | export interface AigcInfo { 195 | aigc_label_type: number 196 | } 197 | 198 | export interface AnimatedImageInfo { 199 | type: number 200 | effect: number 201 | } 202 | 203 | export interface AwemeListAuthor { 204 | uid: string 205 | short_id: string 206 | nickname: string 207 | signature: string 208 | avatar_larger: LabelTop 209 | avatar_thumb: LabelTop 210 | avatar_medium: LabelTop 211 | follow_status: number 212 | aweme_count: number 213 | following_count: number 214 | follower_count: number 215 | favoriting_count: number 216 | total_favorited: number 217 | is_block: boolean 218 | hide_search: boolean 219 | custom_verify: string 220 | unique_id: string 221 | bind_phone: string 222 | special_lock: number 223 | need_recommend: number 224 | has_facebook_token: boolean 225 | has_twitter_token: boolean 226 | fb_expire_time: number 227 | tw_expire_time: number 228 | has_youtube_token: boolean 229 | youtube_expire_time: number 230 | room_id: number 231 | live_verify: number 232 | authority_status: number 233 | verify_info: string 234 | shield_follow_notice: number 235 | shield_digg_notice: number 236 | shield_comment_notice: number 237 | share_info: AuthorShareInfo 238 | with_commerce_entry: boolean 239 | verification_type: number 240 | enterprise_verify_reason: string 241 | is_ad_fake: boolean 242 | followers_detail: null 243 | region: string 244 | account_region: string 245 | commerce_user_level: number 246 | live_agreement: number 247 | platform_sync_info: null 248 | with_shop_entry: boolean 249 | is_discipline_member: boolean 250 | secret: number 251 | has_orders: boolean 252 | prevent_download: boolean 253 | show_image_bubble: boolean 254 | geofencing: null 255 | unique_id_modify_time: number 256 | video_icon: LabelTop 257 | ins_id: string 258 | google_account: string 259 | youtube_channel_id: string 260 | youtube_channel_title: string 261 | apple_account: number 262 | is_phone_binded: boolean 263 | accept_private_policy: boolean 264 | twitter_id: string 265 | twitter_name: string 266 | user_canceled: boolean 267 | has_email: boolean 268 | status: number 269 | create_time: number 270 | avatar_uri: string 271 | follower_status: number 272 | comment_setting: number 273 | duet_setting: number 274 | user_rate: number 275 | download_setting: number 276 | download_prompt_ts: number 277 | react_setting: number 278 | live_commerce: boolean 279 | cover_url: LabelTop[] 280 | language: string 281 | has_insights: boolean 282 | share_qrcode_uri: string 283 | item_list: null 284 | user_mode: number 285 | user_period: number 286 | is_star: boolean 287 | cv_level: string 288 | type_label: any[] 289 | ad_cover_url: null 290 | comment_filter_status: number 291 | avatar_168x168: LabelTop 292 | avatar_300x300: LabelTop 293 | relative_users: null 294 | cha_list: null 295 | sec_uid: string 296 | need_points: null 297 | homepage_bottom_toast: null 298 | can_set_geofencing: null 299 | white_cover_url: null 300 | user_tags: null 301 | stitch_setting: number 302 | bold_fields: null 303 | search_highlight: null 304 | mutual_relation_avatars: null 305 | events: null 306 | matched_friend: MatchedFriend 307 | advance_feature_item_order: null 308 | advanced_feature_info: null 309 | user_profile_guide: null 310 | shield_edit_field_info: null 311 | friends_status: number 312 | can_message_follow_status_list: null 313 | account_labels: null 314 | social_info?: string 315 | } 316 | 317 | export interface MatchedFriend { 318 | video_items: null 319 | } 320 | 321 | export interface AuthorShareInfo { 322 | share_url: string 323 | share_weibo_desc: string 324 | share_desc: string 325 | share_title: string 326 | share_qrcode_url: LabelTop 327 | share_title_myself: string 328 | share_title_other: string 329 | share_desc_info: string 330 | now_invitation_card_image_urls: null 331 | } 332 | 333 | export interface ChaList { 334 | cid: string 335 | cha_name: string 336 | desc: string 337 | schema: string 338 | author: ChaListAuthor 339 | user_count: number 340 | share_info: ChaListShareInfo 341 | connect_music: any[] 342 | type: number 343 | sub_type: number 344 | is_pgcshow: boolean 345 | collect_stat: number 346 | is_challenge: number 347 | view_count: number 348 | is_commerce: boolean 349 | hashtag_profile: string 350 | cha_attrs: null 351 | banner_list: null 352 | show_items: null 353 | search_highlight: null 354 | } 355 | 356 | export interface ChaListAuthor { 357 | followers_detail: null 358 | platform_sync_info: null 359 | geofencing: null 360 | cover_url: null 361 | item_list: null 362 | type_label: null 363 | ad_cover_url: null 364 | relative_users: null 365 | cha_list: null 366 | need_points: null 367 | homepage_bottom_toast: null 368 | can_set_geofencing: null 369 | white_cover_url: null 370 | user_tags: null 371 | bold_fields: null 372 | search_highlight: null 373 | mutual_relation_avatars: null 374 | events: null 375 | advance_feature_item_order: null 376 | advanced_feature_info: null 377 | user_profile_guide: null 378 | shield_edit_field_info: null 379 | can_message_follow_status_list: null 380 | account_labels: null 381 | } 382 | 383 | export interface ChaListShareInfo { 384 | share_url: string 385 | share_weibo_desc: string 386 | share_desc: string 387 | share_title: string 388 | bool_persist: number 389 | share_title_myself: string 390 | share_title_other: string 391 | share_signature_url: string 392 | share_signature_desc: string 393 | share_quote: string 394 | share_desc_info: string 395 | now_invitation_card_image_urls: null 396 | share_link_desc?: string 397 | share_button_display_mode?: number 398 | button_display_stratege_source?: string 399 | } 400 | 401 | export interface CommentConfig { 402 | emoji_recommend_list: null 403 | } 404 | 405 | export interface CommerceInfo { 406 | adv_promotable: boolean 407 | branded_content_type: number 408 | } 409 | 410 | export interface Extra { 411 | start: number 412 | end: number 413 | type: number 414 | hashtag_name: string 415 | hashtag_id: string 416 | is_commerce: boolean 417 | line_idx?: number 418 | user_id?: string 419 | sec_uid?: string 420 | } 421 | 422 | export interface InteractPermission { 423 | duet: number 424 | stitch: number 425 | duet_privacy_setting: number 426 | stitch_privacy_setting: number 427 | upvote: number 428 | allow_adding_to_story: number 429 | allow_create_sticker: AllowCreateSticker 430 | } 431 | 432 | export interface AllowCreateSticker { 433 | status: number 434 | } 435 | 436 | export interface InteractionSticker { 437 | type: number 438 | index: number 439 | track_info: string 440 | attr: string 441 | text_info: string 442 | text_sticker_info: TextStickerInfo 443 | } 444 | 445 | export interface TextStickerInfo { 446 | text_size: number 447 | text_color: string 448 | bg_color: string 449 | text_language: string 450 | alignment: number 451 | source_width: number 452 | source_height: number 453 | } 454 | 455 | export interface InteractionTagInfo { 456 | interest_level: number 457 | video_label_text: string 458 | tagged_users: TaggedUser[] 459 | } 460 | 461 | export interface TaggedUser { 462 | uid: string 463 | unique_id: string 464 | nickname: string 465 | avatar_168x168: LabelTop 466 | avatar_thumb: LabelTop 467 | follow_status: number 468 | follower_status: number 469 | interest_level: number 470 | is_business_account: boolean 471 | invitation_status: number 472 | } 473 | 474 | export interface AwemeListLogInfo { 475 | order: string 476 | } 477 | 478 | export interface OriginalClientText { 479 | markup_text: string 480 | text_extra: TextExtra[] | null 481 | } 482 | 483 | export interface TextExtra { 484 | type: number 485 | hashtag_name: string 486 | is_commerce?: boolean 487 | sub_type?: number 488 | tag_id: string 489 | user_id?: string 490 | } 491 | 492 | export interface RiskInfos { 493 | vote: boolean 494 | warn: boolean 495 | risk_sink: boolean 496 | type: number 497 | content: string 498 | } 499 | 500 | export interface Statistics { 501 | aweme_id: string 502 | comment_count: number 503 | digg_count: number 504 | download_count: number 505 | play_count: number 506 | share_count: number 507 | forward_count: number 508 | lose_count: number 509 | lose_comment_count: number 510 | whatsapp_share_count: number 511 | collect_count: number 512 | } 513 | 514 | export interface Status { 515 | aweme_id: string 516 | is_delete: boolean 517 | allow_share: boolean 518 | allow_comment: boolean 519 | is_private: boolean 520 | with_goods: boolean 521 | private_status: number 522 | in_reviewing: boolean 523 | reviewed: number 524 | self_see: boolean 525 | is_prohibited: boolean 526 | download_status: number 527 | } 528 | 529 | export interface Video { 530 | play_addr: LabelTop 531 | cover: LabelTop 532 | height: number 533 | width: number 534 | dynamic_cover: LabelTop 535 | origin_cover: LabelTop 536 | ratio: string 537 | download_addr: LabelTop 538 | has_watermark: boolean 539 | bit_rate: BitRate[] 540 | duration: number 541 | download_suffix_logo_addr: LabelTop 542 | has_download_suffix_logo_addr: boolean 543 | is_h265: number 544 | cdn_url_expired: number 545 | need_set_token: boolean 546 | CoverTsp: number 547 | misc_download_addrs: string 548 | tags: null 549 | big_thumbs: null 550 | is_bytevc1: number 551 | meta: string 552 | source_HDR_type: number 553 | bit_rate_audio: any[] 554 | cover_is_custom?: boolean 555 | } 556 | 557 | export interface BitRate { 558 | gear_name: GearName 559 | quality_type: number 560 | bit_rate: number 561 | play_addr: LabelTop 562 | is_h265: number 563 | is_bytevc1: number 564 | dub_infos: null 565 | HDR_type: string 566 | HDR_bit: string 567 | } 568 | 569 | export enum GearName { 570 | Lower540_0 = 'lower_540_0', 571 | Lowest540_0 = 'lowest_540_0', 572 | Normal540_0 = 'normal_540_0' 573 | } 574 | 575 | export interface VideoControl { 576 | allow_download: boolean 577 | share_type: number 578 | show_progress_bar: number 579 | draft_progress_bar: number 580 | allow_duet: boolean 581 | allow_react: boolean 582 | prevent_download_type: number 583 | allow_dynamic_wallpaper: boolean 584 | timer_status: number 585 | allow_music: boolean 586 | allow_stitch: boolean 587 | } 588 | 589 | export interface ExtraClass { 590 | now: number 591 | fatal_item_ids: null 592 | } 593 | 594 | export interface TikTokAPIResponseLogInfo { 595 | impr_id: string 596 | pull_type: string 597 | } 598 | 599 | export interface LogPb { 600 | impr_id: string 601 | } 602 | 603 | export interface Image { 604 | display_image: { 605 | uri: string 606 | url_list: string[] 607 | width: number 608 | height: number 609 | url_prefix: string | null 610 | } 611 | owner_watermark_image: { 612 | uri: string 613 | url_list: string[] 614 | width: number 615 | height: number 616 | url_prefix: string | null 617 | } 618 | user_watermark_image: { 619 | uri: string 620 | url_list: string[] 621 | width: number 622 | height: number 623 | url_prefix: string | null 624 | } 625 | thumbnail: { 626 | uri: string 627 | url_list: string[] 628 | width: number 629 | height: number 630 | url_prefix: string | null 631 | } 632 | bitratre_images: string | null 633 | } 634 | 635 | export interface ImagePostInfo { 636 | images: Image[] 637 | image_post_cover: Image[] 638 | post_extra: String 639 | } 640 | -------------------------------------------------------------------------------- /src/types/Live.ts: -------------------------------------------------------------------------------- 1 | export interface LiveWebJSONResponse { 2 | LiveRoom: LiveRoom 3 | } 4 | 5 | export interface LiveRoom { 6 | loadingState: LoadingState 7 | needLogin: boolean 8 | showLiveGate: boolean 9 | isAgeGateRoom: boolean 10 | recommendLiveRooms: any[] 11 | liveRoomStatus: number 12 | liveRoomUserInfo: LiveRoomUserInfo 13 | } 14 | 15 | export interface LoadingState { 16 | getRecommendLive: number 17 | getUserInfo: number 18 | getUserStat: number 19 | } 20 | 21 | export interface LiveRoomUserInfo { 22 | user: User 23 | stats: Stats 24 | liveRoom: LiveRoom2 25 | } 26 | 27 | export interface User { 28 | avatarLarger: string 29 | avatarMedium: string 30 | avatarThumb: string 31 | id: string 32 | nickname: string 33 | secUid: string 34 | secret: boolean 35 | uniqueId: string 36 | verified: boolean 37 | roomId: string 38 | signature: string 39 | status: number 40 | } 41 | 42 | export interface Stats { 43 | followingCount: number 44 | followerCount: number 45 | } 46 | 47 | export interface LiveRoom2 { 48 | coverUrl: string 49 | title: string 50 | startTime: number 51 | status: number 52 | paidEvent: PaidEvent 53 | liveSubOnly: number 54 | liveRoomMode: number 55 | hashTagId: number 56 | gameTagId: number 57 | liveRoomStats: LiveRoomStats 58 | streamData: StreamData 59 | streamId: string 60 | multiStreamScene: number 61 | multiStreamSource: number 62 | hevcStreamData: HevcStreamData 63 | } 64 | 65 | export interface PaidEvent { 66 | event_id: number 67 | paid_type: number 68 | } 69 | 70 | export interface LiveRoomStats { 71 | userCount: number 72 | } 73 | 74 | export interface StreamData { 75 | pull_data: PullData 76 | } 77 | 78 | export interface PullData { 79 | options: Options 80 | stream_data: string 81 | } 82 | 83 | export interface Options { 84 | default_quality: DefaultQuality 85 | qualities: Quality[] 86 | show_quality_button: boolean 87 | } 88 | 89 | export interface DefaultQuality { 90 | icon_type: number 91 | level: number 92 | name: string 93 | resolution: string 94 | sdk_key: string 95 | v_codec: string 96 | } 97 | 98 | export interface Quality { 99 | icon_type: number 100 | level: number 101 | name: string 102 | resolution: string 103 | sdk_key: string 104 | v_codec: string 105 | } 106 | 107 | export interface HevcStreamData { 108 | pull_data: PullData2 109 | } 110 | 111 | export interface PullData2 { 112 | options: Options2 113 | stream_data: string 114 | } 115 | 116 | export interface Options2 { 117 | default_quality: DefaultQuality2 118 | qualities: Quality2[] 119 | show_quality_button: boolean 120 | } 121 | 122 | export interface DefaultQuality2 { 123 | icon_type: number 124 | level: number 125 | name: string 126 | resolution: string 127 | sdk_key: string 128 | v_codec: string 129 | } 130 | 131 | export interface Quality2 { 132 | icon_type: number 133 | level: number 134 | name: string 135 | resolution: string 136 | sdk_key: string 137 | v_codec: string 138 | } 139 | -------------------------------------------------------------------------------- /src/types/Web.ts: -------------------------------------------------------------------------------- 1 | export interface WebJSONResponse { 2 | __DEFAULT_SCOPE__: DefaultScope 3 | } 4 | 5 | export interface DefaultScope { 6 | 'webapp.app-context': WebappAppContext 7 | 'webapp.biz-context': WebappBizContext 8 | 'webapp.i18n-translation': WebappI18nTranslation 9 | 'seo.abtest': SeoAbtest 10 | 'webapp.browserRedirect-context': WebappBrowserRedirectContext 11 | 'webapp.video-detail'?: WebappVideoDetail 12 | 'webapp.a-b': WebappAB 13 | } 14 | 15 | export interface WebappAppContext { 16 | language: string 17 | region: string 18 | appId: number 19 | appType: string 20 | user: User 21 | wid: string 22 | webIdCreatedTime: string 23 | nonce: string 24 | botType: string 25 | requestId: string 26 | clusterRegion: string 27 | abTestVersion: AbTestVersion 28 | csrfToken: string 29 | userAgent: string 30 | encryptedWebid: string 31 | host: string 32 | } 33 | 34 | export interface User { 35 | ftcUser: boolean 36 | secUid: string 37 | uid: string 38 | nickName: string 39 | signature: string 40 | uniqueId: string 41 | createTime: string 42 | hasLivePermission: boolean 43 | roomId: string 44 | region: string 45 | avatarUri: string[] 46 | isPrivateAccount: boolean 47 | hasIMPermission: boolean 48 | hasSearchPermission: boolean 49 | storeRegion: string 50 | suggestAccountBind: boolean 51 | showPrivateBanner: boolean 52 | showScheduleTips: boolean 53 | longVideoMinutes: number 54 | longVideoPopupDisplayedStatus: LongVideoPopupDisplayedStatus 55 | ageGateRegion: string 56 | ageGateTime: string 57 | userMode: number 58 | hasSearchLivePermission: boolean 59 | proAccountInfo: ProAccountInfo 60 | analyticsOn: boolean 61 | redDot: any[] 62 | photoSensitiveVideosSetting: number 63 | hasCollectionsAccess: boolean 64 | hasCollectionsRedDot: boolean 65 | canExpPlaylist: boolean 66 | showPodcastTooltip: boolean 67 | } 68 | 69 | export interface LongVideoPopupDisplayedStatus { 70 | cache_ttl: string 71 | } 72 | 73 | export interface ProAccountInfo { 74 | status: number 75 | analyticsOn: boolean 76 | businessSuiteEntrance: boolean 77 | downloadLink: DownloadLink 78 | } 79 | 80 | export interface DownloadLink {} 81 | 82 | export interface AbTestVersion { 83 | versionName: string 84 | parameters: Parameters 85 | abTestApp: AbTestApp 86 | } 87 | 88 | export interface Parameters { 89 | use_inbox_notice_count_api: UseInboxNoticeCountApi 90 | video_feed_redesign: VideoFeedRedesign 91 | video_serverpush: VideoServerpush 92 | should_highlight_hashtag: ShouldHighlightHashtag 93 | mobile_vodkit: MobileVodkit 94 | mobile_consumption_limit_non_logged_in: MobileConsumptionLimitNonLoggedIn 95 | mobile_consumption_limit_v2: MobileConsumptionLimitV2 96 | remove_poi_anchor_mobile: RemovePoiAnchorMobile 97 | search_video: SearchVideo 98 | mobile_search_test: MobileSearchTest 99 | webapp_login_email_phone: WebappLoginEmailPhone 100 | webapp_switch_account: WebappSwitchAccount 101 | browser_login_redirect: BrowserLoginRedirect 102 | periodic_login_popup_interval: PeriodicLoginPopupInterval 103 | login_option_order_by_metrics: LoginOptionOrderByMetrics 104 | mobile_predictive_data: MobilePredictiveData 105 | one_column_player_size: OneColumnPlayerSize 106 | browser_mode_encourage_login: BrowserModeEncourageLogin 107 | share_button_part1_test: ShareButtonPart1Test 108 | enable_ml_model: EnableMlModel 109 | sign_up_webapp_region_change: SignUpWebappRegionChange 110 | mobile_consumption_limit_logged_in: MobileConsumptionLimitLoggedIn 111 | creator_center_connect: CreatorCenterConnect 112 | xgplayer_preload_config: XgplayerPreloadConfig 113 | last_login_method: LastLoginMethod 114 | xg_volume_test: XgVolumeTest 115 | login_modal_image: LoginModalImage 116 | login_modal_ui_revamp: LoginModalUiRevamp 117 | qr_sso_popup: QrSsoPopup 118 | video_bitrate_adapt: VideoBitrateAdapt 119 | use_follow_v2: UseFollowV2 120 | mobile_consumption_limit_login: MobileConsumptionLimitLogin 121 | non_logged_in_comments: NonLoggedInComments 122 | confirm_logout: ConfirmLogout 123 | volume_normalize: VolumeNormalize 124 | remove_bottom_banner: RemoveBottomBanner 125 | ab_tag: AbTag 126 | add_guide_login_test: AddGuideLoginTest 127 | add_kap_entry: AddKapEntry 128 | add_profile_left_bar: AddProfileLeftBar 129 | add_transcript: AddTranscript 130 | auto_scroll: AutoScroll 131 | browse_mode_autoplay_test: BrowseModeAutoplayTest 132 | browser_mode_creator_tab_3: BrowserModeCreatorTab3 133 | cc_perf_phase1: CcPerfPhase1 134 | clean_fixed_bottom: CleanFixedBottom 135 | close_to_zoom_out_test: CloseToZoomOutTest 136 | comment_refactor_test: CommentRefactorTest 137 | creator_center_connect_global: CreatorCenterConnectGlobal 138 | creator_center_global_comment_management: CreatorCenterGlobalCommentManagement 139 | creator_center_global_post_management: CreatorCenterGlobalPostManagement 140 | creator_center_test: CreatorCenterTest 141 | delay_guest: DelayGuest 142 | desktop_ui_opt: DesktopUiOpt 143 | desktop_ui_reply: DesktopUiReply 144 | digital_wellbeing_web: DigitalWellbeingWeb 145 | enable_about_this_ad: EnableAboutThisAd 146 | enable_ads: EnableAds 147 | enable_continue_play: EnableContinuePlay 148 | enable_fb_sdk: EnableFbSdk 149 | enable_not_interested: EnableNotInterested 150 | enable_profile_pinned_video: EnableProfilePinnedVideo 151 | enhance_video_consumption_test: EnhanceVideoConsumptionTest 152 | exchange_retention_popup: ExchangeRetentionPopup 153 | expand_item_tag: ExpandItemTag 154 | explore_shunt_test: ExploreShuntTest 155 | explore_test: ExploreTest 156 | favorite_test: FavoriteTest 157 | fix_tea_session: FixTeaSession 158 | following_display_live: FollowingDisplayLive 159 | following_red_dot: FollowingRedDot 160 | friends_tab: FriendsTab 161 | fyp_description_in_video: FypDescriptionInVideo 162 | fyp_snap_scroll: FypSnapScroll 163 | has_system_notification_inbox: HasSystemNotificationInbox 164 | husky_param: HuskyParam 165 | increase_detail_page_cover_quantity_test: IncreaseDetailPageCoverQuantityTest 166 | kep_new_ui_login: KepNewUiLogin 167 | kep_video_sort_ctr_exp: KepVideoSortCtrExp 168 | live_abr_version: LiveAbrVersion 169 | live_csr_insert_context: LiveCsrInsertContext 170 | live_detail_non_logged_in_entry: LiveDetailNonLoggedInEntry 171 | live_end_improved_metrics: LiveEndImprovedMetrics 172 | live_event_aggregation: LiveEventAggregation 173 | live_feed_preload: LiveFeedPreload 174 | live_feed_style: LiveFeedStyle 175 | live_golive_entrance: LiveGoliveEntrance 176 | live_i18n_reduce: LiveI18nReduce 177 | live_lcp_perf_optimize: LiveLcpPerfOptimize 178 | live_like: LiveLike 179 | live_login_reflow_btn: LiveLoginReflowBtn 180 | live_new_discover: LiveNewDiscover 181 | live_player_icon: LivePlayerIcon 182 | live_player_mute_text: LivePlayerMuteText 183 | live_player_switch_button: LivePlayerSwitchButton 184 | live_preview_web: LivePreviewWeb 185 | live_pro_show: LiveProShow 186 | live_recharge_by_amount: LiveRechargeByAmount 187 | live_recharge_cashier_google_pay: LiveRechargeCashierGooglePay 188 | live_recharge_cashier_phase3: LiveRechargeCashierPhase3 189 | live_recharge_coins_cache: LiveRechargeCoinsCache 190 | live_recharge_homescreen: LiveRechargeHomescreen 191 | live_recharge_noneu_agreement_optimize: LiveRechargeNoneuAgreementOptimize 192 | live_recharge_paypal_link_result: LiveRechargePaypalLinkResult 193 | live_report_comment_reason_api: LiveReportCommentReasonApi 194 | live_report_reason_api: LiveReportReasonApi 195 | live_room_age_restriction: LiveRoomAgeRestriction 196 | live_room_match: LiveRoomMatch 197 | live_room_non_streaming: LiveRoomNonStreaming 198 | live_studio_download_refactor_pc: LiveStudioDownloadRefactorPc 199 | live_top_viewers: LiveTopViewers 200 | live_wallet_performance_packup: LiveWalletPerformancePackup 201 | live_wallet_recharge_apple_pay: LiveWalletRechargeApplePay 202 | new_item_tag: NewItemTag 203 | optimise_browser_mode: OptimiseBrowserMode 204 | pc_video_playlist_test: PcVideoPlaylistTest 205 | photo_mode_yml: PhotoModeYml 206 | photo_test: PhotoTest 207 | profile_follow_info: ProfileFollowInfo 208 | promote_qr_code: PromoteQrCode 209 | related_videos_video_detail_page: RelatedVideosVideoDetailPage 210 | reverse_expand_item_tag: ReverseExpandItemTag 211 | search_add_live: SearchAddLive 212 | search_add_related_search: SearchAddRelatedSearch 213 | search_bar_style_opt: SearchBarStyleOpt 214 | search_keep_sug_show: SearchKeepSugShow 215 | search_transfer_history: SearchTransferHistory 216 | search_video_lab: SearchVideoLab 217 | seo_breadcrumb_detail: SeoBreadcrumbDetail 218 | seo_desktop: SeoDesktop 219 | should_recom_reduce_icon_risk: ShouldRecomReduceIconRisk 220 | show_aigc_label_web: ShowAigcLabelWeb 221 | sidenav_test: SidenavTest 222 | studio_web_eh_entrance: StudioWebEhEntrance 223 | studio_web_eh_entrance_v2: StudioWebEhEntranceV2 224 | tiktok: Tiktok 225 | tiktok_web: TiktokWeb 226 | translation_reduce: TranslationReduce 227 | tteh_effect_anchor_v1: TtehEffectAnchorV1 228 | ttlive_broadcast_topic_version_two: TtliveBroadcastTopicVersionTwo 229 | ui_layout_alignment: UiLayoutAlignment 230 | use_aligned_copies: UseAlignedCopies 231 | use_error_boundary: UseErrorBoundary 232 | use_profile_avatar: UseProfileAvatar 233 | video_detail_auto_pip_opt: VideoDetailAutoPipOpt 234 | video_detail_page_video_play: VideoDetailPageVideoPlay 235 | video_detail_related_refetch: VideoDetailRelatedRefetch 236 | video_detail_yml_ui: VideoDetailYmlUi 237 | video_tdk_chatgpt_user_pc: VideoTdkChatgptUserPc 238 | video_topic: VideoTopic 239 | web_player_refactor: WebPlayerRefactor 240 | webapp_explore_category: WebappExploreCategory 241 | webapp_jotai_foryou: WebappJotaiForyou 242 | webapp_preview_cover: WebappPreviewCover 243 | webapp_recommend_language: WebappRecommendLanguage 244 | webapp_repost_label: WebappRepostLabel 245 | webapp_seo_photomode_user_exp: WebappSeoPhotomodeUserExp 246 | webapp_video_detail_page_related_mask: WebappVideoDetailPageRelatedMask 247 | webcast: Webcast 248 | } 249 | 250 | export interface UseInboxNoticeCountApi { 251 | vid: string 252 | } 253 | 254 | export interface VideoFeedRedesign { 255 | vid: string 256 | } 257 | 258 | export interface VideoServerpush { 259 | vid: string 260 | } 261 | 262 | export interface ShouldHighlightHashtag { 263 | vid: string 264 | } 265 | 266 | export interface MobileVodkit { 267 | vid: string 268 | } 269 | 270 | export interface MobileConsumptionLimitNonLoggedIn { 271 | vid: string 272 | } 273 | 274 | export interface MobileConsumptionLimitV2 { 275 | vid: string 276 | } 277 | 278 | export interface RemovePoiAnchorMobile { 279 | vid: string 280 | } 281 | 282 | export interface SearchVideo { 283 | vid: string 284 | botVid: string 285 | } 286 | 287 | export interface MobileSearchTest { 288 | vid: string 289 | } 290 | 291 | export interface WebappLoginEmailPhone { 292 | vid: string 293 | } 294 | 295 | export interface WebappSwitchAccount { 296 | vid: string 297 | } 298 | 299 | export interface BrowserLoginRedirect { 300 | vid: string 301 | } 302 | 303 | export interface PeriodicLoginPopupInterval { 304 | vid: string 305 | } 306 | 307 | export interface LoginOptionOrderByMetrics { 308 | vid: string 309 | } 310 | 311 | export interface MobilePredictiveData { 312 | vid: string 313 | } 314 | 315 | export interface OneColumnPlayerSize { 316 | vid: string 317 | } 318 | 319 | export interface BrowserModeEncourageLogin { 320 | vid: string 321 | } 322 | 323 | export interface ShareButtonPart1Test { 324 | vid: string 325 | } 326 | 327 | export interface EnableMlModel { 328 | vid: string 329 | } 330 | 331 | export interface SignUpWebappRegionChange { 332 | vid: string 333 | } 334 | 335 | export interface MobileConsumptionLimitLoggedIn { 336 | vid: string 337 | } 338 | 339 | export interface CreatorCenterConnect { 340 | vid: string 341 | } 342 | 343 | export interface XgplayerPreloadConfig { 344 | vid: string 345 | } 346 | 347 | export interface LastLoginMethod { 348 | vid: string 349 | } 350 | 351 | export interface XgVolumeTest { 352 | vid: string 353 | } 354 | 355 | export interface LoginModalImage { 356 | vid: string 357 | } 358 | 359 | export interface LoginModalUiRevamp { 360 | vid: string 361 | } 362 | 363 | export interface QrSsoPopup { 364 | vid: string 365 | } 366 | 367 | export interface VideoBitrateAdapt { 368 | vid: string 369 | } 370 | 371 | export interface UseFollowV2 { 372 | vid: string 373 | } 374 | 375 | export interface MobileConsumptionLimitLogin { 376 | vid: string 377 | } 378 | 379 | export interface NonLoggedInComments { 380 | vid: string 381 | } 382 | 383 | export interface ConfirmLogout { 384 | vid: string 385 | } 386 | 387 | export interface VolumeNormalize { 388 | vid: string 389 | } 390 | 391 | export interface RemoveBottomBanner { 392 | vid: string 393 | } 394 | 395 | export interface AbTag { 396 | merge_risk_event: number 397 | } 398 | 399 | export interface AddGuideLoginTest { 400 | vid: string 401 | } 402 | 403 | export interface AddKapEntry { 404 | vid: string 405 | } 406 | 407 | export interface AddProfileLeftBar { 408 | vid: string 409 | } 410 | 411 | export interface AddTranscript { 412 | vid: string 413 | } 414 | 415 | export interface AutoScroll { 416 | vid: string 417 | } 418 | 419 | export interface BrowseModeAutoplayTest { 420 | vid: string 421 | } 422 | 423 | export interface BrowserModeCreatorTab3 { 424 | vid: string 425 | } 426 | 427 | export interface CcPerfPhase1 { 428 | vid: Vid 429 | } 430 | 431 | export interface Vid { 432 | isCreatorCenterContextEnabled: boolean 433 | isInsightV2Enabled: boolean 434 | isOfflineI18nEnabled: boolean 435 | isParallelIframeEnabled: boolean 436 | isPhase2Enabled: boolean 437 | isPrefetchIframeResourceEnabled: boolean 438 | isServerSideTranslationEnabled: boolean 439 | } 440 | 441 | export interface CleanFixedBottom { 442 | vid: string 443 | } 444 | 445 | export interface CloseToZoomOutTest { 446 | vid: string 447 | } 448 | 449 | export interface CommentRefactorTest { 450 | vid: string 451 | } 452 | 453 | export interface CreatorCenterConnectGlobal { 454 | vid: string 455 | } 456 | 457 | export interface CreatorCenterGlobalCommentManagement { 458 | vid: string 459 | } 460 | 461 | export interface CreatorCenterGlobalPostManagement { 462 | vid: string 463 | } 464 | 465 | export interface CreatorCenterTest { 466 | vid: string 467 | } 468 | 469 | export interface DelayGuest { 470 | vid: string 471 | } 472 | 473 | export interface DesktopUiOpt { 474 | vid: string 475 | } 476 | 477 | export interface DesktopUiReply { 478 | vid: string 479 | } 480 | 481 | export interface DigitalWellbeingWeb { 482 | vid: string 483 | } 484 | 485 | export interface EnableAboutThisAd { 486 | vid: string 487 | } 488 | 489 | export interface EnableAds { 490 | vid: string 491 | } 492 | 493 | export interface EnableContinuePlay { 494 | vid: string 495 | } 496 | 497 | export interface EnableFbSdk { 498 | vid: string 499 | } 500 | 501 | export interface EnableNotInterested { 502 | vid: string 503 | } 504 | 505 | export interface EnableProfilePinnedVideo { 506 | vid: string 507 | } 508 | 509 | export interface EnhanceVideoConsumptionTest { 510 | vid: string 511 | } 512 | 513 | export interface ExchangeRetentionPopup { 514 | vid: string 515 | } 516 | 517 | export interface ExpandItemTag { 518 | vid: string 519 | } 520 | 521 | export interface ExploreShuntTest { 522 | vid: string 523 | } 524 | 525 | export interface ExploreTest { 526 | vid: string 527 | } 528 | 529 | export interface FavoriteTest { 530 | vid: string 531 | } 532 | 533 | export interface FixTeaSession { 534 | vid: string 535 | } 536 | 537 | export interface FollowingDisplayLive { 538 | vid: string 539 | } 540 | 541 | export interface FollowingRedDot { 542 | vid: string 543 | } 544 | 545 | export interface FriendsTab { 546 | vid: string 547 | } 548 | 549 | export interface FypDescriptionInVideo { 550 | vid: string 551 | } 552 | 553 | export interface FypSnapScroll { 554 | vid: string 555 | } 556 | 557 | export interface HasSystemNotificationInbox { 558 | vid: string 559 | } 560 | 561 | export interface HuskyParam { 562 | client_sdk_param: ClientSdkParam 563 | only_remote_fetch_meta: boolean 564 | } 565 | 566 | export interface ClientSdkParam { 567 | enable_merge_request_web: number 568 | } 569 | 570 | export interface IncreaseDetailPageCoverQuantityTest { 571 | vid: string 572 | } 573 | 574 | export interface KepNewUiLogin { 575 | vid: string 576 | } 577 | 578 | export interface KepVideoSortCtrExp { 579 | vid: string 580 | } 581 | 582 | export interface LiveAbrVersion { 583 | vid: string 584 | } 585 | 586 | export interface LiveCsrInsertContext { 587 | vid: string 588 | } 589 | 590 | export interface LiveDetailNonLoggedInEntry { 591 | seconds: number 592 | vid: string 593 | } 594 | 595 | export interface LiveEndImprovedMetrics { 596 | vid: string 597 | } 598 | 599 | export interface LiveEventAggregation { 600 | vid: string 601 | } 602 | 603 | export interface LiveFeedPreload { 604 | vid: string 605 | } 606 | 607 | export interface LiveFeedStyle { 608 | vid: string 609 | } 610 | 611 | export interface LiveGoliveEntrance { 612 | vid: string 613 | } 614 | 615 | export interface LiveI18nReduce { 616 | vid: string 617 | } 618 | 619 | export interface LiveLcpPerfOptimize { 620 | vid: string 621 | } 622 | 623 | export interface LiveLike { 624 | vid: string 625 | } 626 | 627 | export interface LiveLoginReflowBtn { 628 | vid: string 629 | } 630 | 631 | export interface LiveNewDiscover { 632 | vid: string 633 | } 634 | 635 | export interface LivePlayerIcon { 636 | vid: string 637 | } 638 | 639 | export interface LivePlayerMuteText { 640 | vid: string 641 | } 642 | 643 | export interface LivePlayerSwitchButton { 644 | vid: string 645 | } 646 | 647 | export interface LivePreviewWeb { 648 | vid: string 649 | } 650 | 651 | export interface LiveProShow { 652 | vid: string 653 | } 654 | 655 | export interface LiveRechargeByAmount { 656 | vid: string 657 | } 658 | 659 | export interface LiveRechargeCashierGooglePay { 660 | vid: string 661 | } 662 | 663 | export interface LiveRechargeCashierPhase3 { 664 | vid: string 665 | } 666 | 667 | export interface LiveRechargeCoinsCache { 668 | vid: string 669 | } 670 | 671 | export interface LiveRechargeHomescreen { 672 | vid: string 673 | } 674 | 675 | export interface LiveRechargeNoneuAgreementOptimize { 676 | vid: string 677 | } 678 | 679 | export interface LiveRechargePaypalLinkResult { 680 | vid: string 681 | } 682 | 683 | export interface LiveReportCommentReasonApi { 684 | vid: string 685 | } 686 | 687 | export interface LiveReportReasonApi { 688 | vid: string 689 | } 690 | 691 | export interface LiveRoomAgeRestriction { 692 | vid: string 693 | } 694 | 695 | export interface LiveRoomMatch { 696 | vid: string 697 | } 698 | 699 | export interface LiveRoomNonStreaming { 700 | vid: string 701 | } 702 | 703 | export interface LiveStudioDownloadRefactorPc { 704 | vid: string 705 | } 706 | 707 | export interface LiveTopViewers { 708 | vid: string 709 | } 710 | 711 | export interface LiveWalletPerformancePackup { 712 | vid: string 713 | } 714 | 715 | export interface LiveWalletRechargeApplePay { 716 | vid: string 717 | } 718 | 719 | export interface NewItemTag { 720 | vid: string 721 | } 722 | 723 | export interface OptimiseBrowserMode { 724 | vid: string 725 | } 726 | 727 | export interface PcVideoPlaylistTest { 728 | vid: string 729 | } 730 | 731 | export interface PhotoModeYml { 732 | vid: string 733 | } 734 | 735 | export interface PhotoTest { 736 | vid: string 737 | } 738 | 739 | export interface ProfileFollowInfo { 740 | vid: string 741 | } 742 | 743 | export interface PromoteQrCode { 744 | vid: string 745 | } 746 | 747 | export interface RelatedVideosVideoDetailPage { 748 | vid: string 749 | } 750 | 751 | export interface ReverseExpandItemTag { 752 | vid: string 753 | } 754 | 755 | export interface SearchAddLive { 756 | vid: string 757 | } 758 | 759 | export interface SearchAddRelatedSearch { 760 | vid: string 761 | } 762 | 763 | export interface SearchBarStyleOpt { 764 | vid: string 765 | } 766 | 767 | export interface SearchKeepSugShow { 768 | vid: string 769 | } 770 | 771 | export interface SearchTransferHistory { 772 | vid: string 773 | } 774 | 775 | export interface SearchVideoLab { 776 | vid: string 777 | } 778 | 779 | export interface SeoBreadcrumbDetail { 780 | vid: string 781 | } 782 | 783 | export interface SeoDesktop { 784 | vid: string 785 | } 786 | 787 | export interface ShouldRecomReduceIconRisk { 788 | vid: string 789 | } 790 | 791 | export interface ShowAigcLabelWeb { 792 | vid: string 793 | } 794 | 795 | export interface SidenavTest { 796 | vid: string 797 | } 798 | 799 | export interface StudioWebEhEntrance { 800 | vid: string 801 | } 802 | 803 | export interface StudioWebEhEntranceV2 { 804 | vid: string 805 | } 806 | 807 | export interface Tiktok { 808 | private_account_prompt_for_u18: number 809 | use_aligned_copies: number 810 | } 811 | 812 | export interface TiktokWeb { 813 | cancel_ba_bulk_upload: number 814 | capcut_entry_group: number 815 | enable_cloud_draft: string 816 | enable_local_draft: string 817 | enable_new_playlist: string 818 | fbv_notice_enable: number 819 | opt_v1_new_entrance_v3: number 820 | opt_v1_new_upload_ui: number 821 | post_polling_version: number 822 | show_aigc_toggle: number 823 | tts_product_anchor: number 824 | web_creation_cover_tool: number 825 | } 826 | 827 | export interface TranslationReduce { 828 | vid: string 829 | } 830 | 831 | export interface TtehEffectAnchorV1 { 832 | vid: string 833 | } 834 | 835 | export interface TtliveBroadcastTopicVersionTwo { 836 | vid: string 837 | } 838 | 839 | export interface UiLayoutAlignment { 840 | vid: string 841 | } 842 | 843 | export interface UseAlignedCopies { 844 | vid: string 845 | } 846 | 847 | export interface UseErrorBoundary { 848 | vid: string 849 | } 850 | 851 | export interface UseProfileAvatar { 852 | vid: string 853 | } 854 | 855 | export interface VideoDetailAutoPipOpt { 856 | vid: string 857 | } 858 | 859 | export interface VideoDetailPageVideoPlay { 860 | vid: string 861 | } 862 | 863 | export interface VideoDetailRelatedRefetch { 864 | vid: string 865 | } 866 | 867 | export interface VideoDetailYmlUi { 868 | vid: string 869 | } 870 | 871 | export interface VideoTdkChatgptUserPc { 872 | vid: string 873 | } 874 | 875 | export interface VideoTopic { 876 | vid: string 877 | } 878 | 879 | export interface WebPlayerRefactor { 880 | vid: string 881 | } 882 | 883 | export interface WebappExploreCategory { 884 | vid: string 885 | } 886 | 887 | export interface WebappJotaiForyou { 888 | vid: string 889 | } 890 | 891 | export interface WebappPreviewCover { 892 | vid: string 893 | } 894 | 895 | export interface WebappRecommendLanguage { 896 | vid: string 897 | } 898 | 899 | export interface WebappRepostLabel { 900 | vid: string 901 | } 902 | 903 | export interface WebappSeoPhotomodeUserExp { 904 | vid: string 905 | } 906 | 907 | export interface WebappVideoDetailPageRelatedMask { 908 | vid: string 909 | } 910 | 911 | export interface Webcast { 912 | web_drawer_show_explore: boolean 913 | web_follow_guide_strategy_group: number 914 | } 915 | 916 | export interface AbTestApp { 917 | parameters: Parameters2 918 | } 919 | 920 | export interface Parameters2 { 921 | tiktok: Tiktok2 922 | } 923 | 924 | export interface Tiktok2 { 925 | long_video_popup_display_optimization: boolean 926 | } 927 | 928 | export interface WebappBizContext { 929 | os: string 930 | isMobile: boolean 931 | isAndroid: boolean 932 | isIOS: boolean 933 | jumpType: string 934 | navList: NavList[] 935 | kapLinks: KapLink[] 936 | config: Config 937 | domains: Domains 938 | downloadLink: DownloadLink2 939 | deviceLimitRegisterExpired: boolean 940 | subdivisions: string[] 941 | geo: string[] 942 | geoCity: GeoCity 943 | isGoogleBot: boolean 944 | isBingBot: boolean 945 | isBot: boolean 946 | isSearchEngineBot: boolean 947 | isTTP: boolean 948 | dateFmtLocale: DateFmtLocale 949 | videoPlayerConfig: VideoPlayerConfig 950 | playbackNormalizePath: PlaybackNormalizePath 951 | bitrateConfig: BitrateConfig 952 | searchVideoForLoggedin: boolean 953 | studioDownloadEntrance: StudioDownloadEntrance 954 | liveSuggestConfig: LiveSuggestConfig 955 | liveAnchorEntrance: LiveAnchorEntrance 956 | liveStudioEnable: boolean 957 | xgplayerInitHost: XgplayerInitHost 958 | videoOrder: VideoOrder 959 | searchLiveForLoggedin: boolean 960 | canUseQuery: boolean 961 | bitrateSelectorConfigs: BitrateSelectorConfigs 962 | idc: string 963 | vregion: string 964 | vgeo: string 965 | videoCoverSettings: VideoCoverSettings 966 | hevcRobustness: HevcRobustness 967 | apiKeys: ApiKeys 968 | } 969 | 970 | export interface NavList { 971 | title: string 972 | children: Children[] 973 | } 974 | 975 | export interface Children { 976 | title: string 977 | href: string 978 | key?: string 979 | } 980 | 981 | export interface KapLink { 982 | title: string 983 | children: Children2[] 984 | } 985 | 986 | export interface Children2 { 987 | lang: string[] 988 | links: Link[] 989 | } 990 | 991 | export interface Link { 992 | title: string 993 | href: string 994 | } 995 | 996 | export interface Config { 997 | featureFlags: FeatureFlags 998 | desktopAppDownloadLink: DesktopAppDownloadLink 999 | signUpOpen: boolean 1000 | cookieBanner: CookieBanner 1001 | isGrayFilter: boolean 1002 | nickNameControlDay: string 1003 | desktopAppSurveyLink: DesktopAppSurveyLink 1004 | desktopWebSurveyLink: DesktopWebSurveyLink 1005 | } 1006 | 1007 | export interface FeatureFlags { 1008 | feature_tt4b_ads: boolean 1009 | business_account_open: boolean 1010 | support_multiline_desc: boolean 1011 | pc_video_playlist: boolean 1012 | feature_mobile_ui_opt_stage2: boolean 1013 | add_recipe_card: boolean 1014 | collapse_seo_header: boolean 1015 | collapse_seo_header_mobile: boolean 1016 | seo_enable_new_poi_page: boolean 1017 | enable_privacy_center: boolean 1018 | hashtag_viewcount: boolean 1019 | should_show_effect_detail_page: boolean 1020 | } 1021 | 1022 | export interface DesktopAppDownloadLink { 1023 | mac: string 1024 | win: string 1025 | } 1026 | 1027 | export interface CookieBanner { 1028 | load_dynamically: boolean 1029 | decline_btn_staged_rollout_area: string[] 1030 | resource: Resource 1031 | i18n: I18n 1032 | } 1033 | 1034 | export interface Resource { 1035 | prefix: string 1036 | themes: string[] 1037 | esm: string 1038 | nomodule: string 1039 | version: string 1040 | } 1041 | 1042 | export interface I18n { 1043 | cookieBannerTitle: string 1044 | cookieBannerTitleNew: string 1045 | cookieBannerSubTitle: string 1046 | cookieBannerSubTitleNew: string 1047 | cookieBannerSubTitleV2: string 1048 | cookieBannerBtnManage: string 1049 | cookieBannerBtnAccept: string 1050 | cookieBannerBtnDecline: string 1051 | cookiesBannerDetails: string 1052 | cookiesBannerCookiesPolicy: string 1053 | cookiesBannerAccept: string 1054 | webDoNotSellSettingsSavedToast: string 1055 | cookieSettingManageYourCookieTitle: string 1056 | cookieSettingSave: string 1057 | cookieSettingAnalyticsAndMarketing: string 1058 | cookieSettingNecessary: string 1059 | cookieSettingNecessarySubtitle: string 1060 | cookieSettingNecessaryV2: string 1061 | cookieSettingNecessarySubtitleV2: string 1062 | cookieSettingAnalyticsAndMarketingSubtitle: string 1063 | cookieSettingAnalyticsAndMarketingSubtitleV2: string 1064 | cookieManageTip: string 1065 | } 1066 | 1067 | export interface DesktopAppSurveyLink { 1068 | default: string 1069 | vn: string 1070 | } 1071 | 1072 | export interface DesktopWebSurveyLink { 1073 | new: string 1074 | old: string 1075 | } 1076 | 1077 | export interface Domains { 1078 | kind: string 1079 | captcha: string 1080 | imApi: string 1081 | imFrontier: string 1082 | mTApi: string 1083 | rootApi: string 1084 | secSDK: string 1085 | slardar: string 1086 | starling: string 1087 | tea: string 1088 | teaChannel: string 1089 | teaChannelType: string 1090 | libraWebSDK: string 1091 | webcastApi: string 1092 | webcastRootApi: string 1093 | pipoApi: string 1094 | tcc: string 1095 | locationApi: string 1096 | } 1097 | 1098 | export interface DownloadLink2 { 1099 | microsoft: Microsoft 1100 | apple: Apple 1101 | amazon: Amazon 1102 | google: Google 1103 | } 1104 | 1105 | export interface Microsoft { 1106 | visible: boolean 1107 | normal: string 1108 | } 1109 | 1110 | export interface Apple { 1111 | visible: boolean 1112 | normal: string 1113 | } 1114 | 1115 | export interface Amazon { 1116 | visible: boolean 1117 | normal: string 1118 | } 1119 | 1120 | export interface Google { 1121 | visible: boolean 1122 | normal: string 1123 | } 1124 | 1125 | export interface GeoCity { 1126 | City: string 1127 | Subdivisions: string 1128 | OriginalSubdivisions: OriginalSubdivision[] 1129 | SubdivisionsArr: string[] 1130 | } 1131 | 1132 | export interface OriginalSubdivision { 1133 | GeoNameID: string 1134 | ASCIName: string 1135 | Name: string 1136 | LocalID: string 1137 | } 1138 | 1139 | export interface DateFmtLocale { 1140 | name: string 1141 | months: string[] 1142 | monthsShort: string[] 1143 | weekdays: string[] 1144 | weekdaysShort: string[] 1145 | weekdaysMin: string[] 1146 | longDateFormat: LongDateFormat 1147 | meridiem: Meridiem 1148 | } 1149 | 1150 | export interface LongDateFormat { 1151 | LT: string 1152 | LTS: string 1153 | L: string 1154 | LL: string 1155 | LLL: string 1156 | LLLL: string 1157 | l: string 1158 | ll: string 1159 | lll: string 1160 | llll: string 1161 | 'LL-Y': string 1162 | } 1163 | 1164 | export interface Meridiem { 1165 | am: string 1166 | pm: string 1167 | AM: string 1168 | PM: string 1169 | } 1170 | 1171 | export interface VideoPlayerConfig { 1172 | fallback: boolean 1173 | } 1174 | 1175 | export interface PlaybackNormalizePath { 1176 | path: string[] 1177 | } 1178 | 1179 | export interface BitrateConfig { 1180 | bitrateLower: number 1181 | bitrateRange: number[] 1182 | bitrateUpper: number 1183 | mode: string 1184 | paramBf: number 1185 | paramBp: number 1186 | paramLower: number 1187 | paramUpper: number 1188 | paramUpperBl: number 1189 | paramVl1: number 1190 | paramVl2: number 1191 | paramVlLower: number 1192 | paramVlUpper: number 1193 | slidingWindowCountThreshold: number 1194 | slidingWindowExtraction: string 1195 | slidingWindowType: string 1196 | slidingWindowWeight: string 1197 | slidingWindowWeightThreshold: number 1198 | } 1199 | 1200 | export interface StudioDownloadEntrance { 1201 | regions: string[] 1202 | userRegions: string[] 1203 | allRegions: boolean 1204 | userBlockRegions: string[] 1205 | userBlockGeoNameIDs: string[] 1206 | } 1207 | 1208 | export interface LiveSuggestConfig { 1209 | isBlockedArea: boolean 1210 | isRiskArea: boolean 1211 | } 1212 | 1213 | export interface LiveAnchorEntrance { 1214 | liveCenter: boolean 1215 | creatorHub: boolean 1216 | liveStudio: boolean 1217 | } 1218 | 1219 | export interface XgplayerInitHost { 1220 | group1: string[] 1221 | group2: string[] 1222 | } 1223 | 1224 | export interface VideoOrder { 1225 | videoOrder: VideoOrder2[] 1226 | } 1227 | 1228 | export interface VideoOrder2 { 1229 | property: string 1230 | detail?: number[] 1231 | order?: string 1232 | } 1233 | 1234 | export interface BitrateSelectorConfigs { 1235 | configs: Config2[] 1236 | } 1237 | 1238 | export interface Config2 { 1239 | paramBf: number 1240 | paramBp: number 1241 | paramUpper: number 1242 | paramLower: number 1243 | paramUpperBl: number 1244 | paramVl1: number 1245 | paramVl2: number 1246 | paramVlUpper: number 1247 | paramVlLower: number 1248 | bitrateUpper: number 1249 | bitrateLower: number 1250 | slidingWindowType: string 1251 | slidingWindowWeight: string 1252 | slidingWindowWeightThreshold: number 1253 | slidingWindowCountThreshold: number 1254 | slidingWindowExtraction: string 1255 | bitrateRange: number[] 1256 | mode: string 1257 | quality_filter: QualityFilter 1258 | white_list: any[] 1259 | autoBitrateParams: AutoBitrateParams 1260 | defaultBitrate: number 1261 | } 1262 | 1263 | export interface QualityFilter {} 1264 | 1265 | export interface AutoBitrateParams { 1266 | paramA: number 1267 | paramB: number 1268 | paramC: number 1269 | paramD: number 1270 | minBitrate: number 1271 | } 1272 | 1273 | export interface VideoCoverSettings { 1274 | format: number 1275 | acceptHeader: string 1276 | _ssrCount: number 1277 | } 1278 | 1279 | export interface HevcRobustness { 1280 | useHevcRobustTest: boolean 1281 | forceRobustTest: string[] 1282 | } 1283 | 1284 | export interface ApiKeys { 1285 | firebase: string 1286 | } 1287 | 1288 | export interface WebappI18nTranslation { 1289 | Webapp: Webapp 1290 | } 1291 | 1292 | export interface Webapp { 1293 | suggested_search_feedback1: string 1294 | suggested_search_feedback2: string 1295 | suggested_search_feedback3: string 1296 | suggested_search_feedback4: string 1297 | suggested_search_feedback5: string 1298 | suggested_search_feedback6: string 1299 | suggested_search_feedback7: string 1300 | suggested_search_feedback8: string 1301 | suggested_search_feedback9: string 1302 | suggested_search_feedback10: string 1303 | suggested_search_feedback11: string 1304 | suggested_search_feedback12: string 1305 | suggested_search_feedback13: string 1306 | 'Share to': string 1307 | friends: string 1308 | following: string 1309 | messages: string 1310 | Web_logout_modal_header: string 1311 | Web_logout_modal_body: string 1312 | Inbox_New: string 1313 | 'Log out': string 1314 | Web_loginDropdown_switchAccount: string 1315 | Web_removeAccount_modal_header: string 1316 | Web_removeAccount_modal_body: string 1317 | Cancel: string 1318 | Web_removeAccount_btn: string 1319 | Web_switchAccount_modal_manageAccount: string 1320 | Web_switchAccount_modal_addAccount: string 1321 | Web_removeAccount_doneEditing_btn: string 1322 | incorrect_code: string 1323 | common_login_panel_title: string 1324 | webapp_coin_recharge_login: string 1325 | WebApp_coin_recharge_9: string 1326 | login_to_search: string 1327 | nonloggedinsearch_popup_header_v1: string 1328 | classifyV1AWeb_webAppDesktop_maskLayer_bodyDesc: string 1329 | seo_pcweb_logIn_header: string 1330 | delete: string 1331 | reactivate_h1: string 1332 | reactivate_btn: string 1333 | optimize_web_open_notnow_cta: string 1334 | optimize_web_open_tiktok_cta: string 1335 | optimize_web_full_app_header: string 1336 | optimize_web_full_app_body: string 1337 | pcWeb_guestLogin_without: string 1338 | pcWeb_guestLogin_withoutSignup: string 1339 | login_popup_modal_header: string 1340 | guestmode_signup_or: string 1341 | encouragePreviousLoginPlatform_loginPage_loginBadge_body: string 1342 | qr_code_login_prompt_popup_header: string 1343 | tiktoktv_login_modal_loginscreen_scanqr1: string 1344 | tiktoktv_login_modal_loginscreen_scanqr2: string 1345 | login_fb_phoneLinked_toast: string 1346 | login_fb_emailLinked_toast: string 1347 | accessibilityLabels_login_modal_eyeClosedIcon: string 1348 | accessibilityLabels_login_modal_eyeOpenIcon: string 1349 | tv_webLogin_login_header: string 1350 | accessibilityLabels_login_form_placeholder_countryCode: string 1351 | webapp_orContinueWith: string 1352 | tv_webLogin_enterCode_bodyv2: string 1353 | tv_webLogin_enterCode_altMethod: string 1354 | tiktok_instant_app_loading_status_header: string 1355 | accessibilityLabels_search_button: string 1356 | regionOption_selectCountry_list_description: string 1357 | regionOption_selectCountry_list_title: string 1358 | accessibilityLabels_signup_form_placeholder_month: string 1359 | accessibilityLabels_signup_form_placeholder_day: string 1360 | accessibilityLabels_signup_form_placeholder_year: string 1361 | webapp_loginModal_qrCode: string 1362 | HUToS_signupConsent_halfSheet_headline: string 1363 | HUToS_signupConsent_halfSheet_par1: string 1364 | HUToS_signupConsent_halfSheet_par1tos: string 1365 | HUToS_signupConsent_halfSheet_par1pp: string 1366 | HUToS_signupConsent_halfSheet_par1cp: string 1367 | HUToS_signupConsent_halfSheet_par2: string 1368 | HUToS_signupConsent_halfSheet_par2sot: string 1369 | HUToS_signupConsent_halfSheet_par2ph: string 1370 | HUToS_signupConsent_halfSheet_declineButton: string 1371 | HUToS_signupConsent_halfSheet_acceptButton: string 1372 | regionOption_signUp_COdisclaimer_description: string 1373 | regionOption_signUp_disclaimer_description: string 1374 | regionOption_signUp_disclaimer_placeholder: string 1375 | regionOption_signUp_nonEUdisclaimer_description: string 1376 | common_notification_unlogged_button: string 1377 | title_private_on: string 1378 | descrip_private_on_signup: string 1379 | link_learn_more_private_accounts_signup: string 1380 | button_signup_private_on: string 1381 | OK: string 1382 | login_fb_noLonger_LinkPhoneReminder: string 1383 | login_fb_noLonger_LoginWithPhoneNextTime: string 1384 | login_fb_noLonger_phone_send_cta: string 1385 | "login_fb_noLonger_can'tVerifyPhone": string 1386 | "login_fb_noLonger_can'tVerifyPhone_useEmail": string 1387 | login_fb_link_cta: string 1388 | login_fb_noLonger_LinkEmailAddress: string 1389 | login_fb_noLonger_EmailLoginAlternative: string 1390 | login_fb_noLonger_GiveFeedback: string 1391 | "login_fb_noLonger_can'tVerifyEmail": string 1392 | "login_fb_noLonger_can'tVerifyEmail_usePhone": string 1393 | login_fb_noLonger_LinkPhoneNumber: string 1394 | login_fb_noLonger_LinkPhoneNumberReminder: string 1395 | login_fb_noLonger_LinkPhone: string 1396 | login_fb_noLonger_notNow_cta: string 1397 | reactivate_toast: string 1398 | regionOption_selectCountry_list_confirmation: string 1399 | accessibilityLabels_signup_form_back: string 1400 | accessibilityLabels_login_form_back: string 1401 | grid: string 1402 | pc_web_scroll_header: string 1403 | pc_web_scroll_body: string 1404 | webapp_feed_redesign_allcomments: string 1405 | comment_off: string 1406 | video_details_page_comment_field_cta: string 1407 | comment_disable_notfollow: string 1408 | music_detail_unavailable_1: string 1409 | video_label_private: string 1410 | 'Friends only': string 1411 | author: string 1412 | pc_web_more_btn: string 1413 | pc_web_less_btn: string 1414 | photosensitive_skepped_toast: string 1415 | pc_web_report_btn: string 1416 | Report: string 1417 | Share: string 1418 | share: string 1419 | pc_web_keyboard_btn: string 1420 | accessibilityLabels_link_userProfile: string 1421 | server_error_title: string 1422 | server_error_sub: string 1423 | refresh: string 1424 | SEO_homepage_title: string 1425 | SEO_homepage_desc: string 1426 | Home: string 1427 | personalisedSearch_searchResults_moreOptions_listItem4: string 1428 | 'Thank you for your feedback': string 1429 | search_rs_report_not_relevant: string 1430 | others_searched_for: string 1431 | 'Sorry, something wrong with the server, please try again.': string 1432 | try_again_btn: string 1433 | no_results: string 1434 | no_results_for: string 1435 | no_results_desc: string 1436 | sms_NGO: string 1437 | Followers: string 1438 | search_account: string 1439 | search_see_more: string 1440 | pm_main_live_entry_final: string 1441 | search_top: string 1442 | search_video: string 1443 | search_nomoreresults_text: string 1444 | 'No videos with this hashtag yet': string 1445 | 'Looking for videos? Try browsing our trending creators, hashtags, and sounds.': string 1446 | playlist_webapp_profileview_playlists_numberviews: string 1447 | views: string 1448 | playlist_webapp_profileview_playlists_numbervid: string 1449 | posts: string 1450 | playlist_webapp_toast_error_cheatPlaylist: string 1451 | playlist_webapp_toast_error_tryagain: string 1452 | playlist_webapp_toast_created: string 1453 | playlist_webapp_creation_backBtn: string 1454 | playlist_webapp_creation_header_create: string 1455 | playlist_webapp_creation_desc: string 1456 | playlist_webapp_upload_dropdown_nameaplaylist: string 1457 | videos: string 1458 | playlist_webapp_upload_addtoplaylist: string 1459 | playlist_webapp_creation_selectvid_desc: string 1460 | playlist_webapp_creation_btn_cancel: string 1461 | playlist_webapp_creation_btn_create: string 1462 | blue_v_change_username_review_modal_desc: string 1463 | blue_v_change_name_review_modal_desc: string 1464 | blue_v_webapp_change_name_review_modal_desc: string 1465 | blue_v_change_name_review_modal_title: string 1466 | blue_v_change_name_review_cancel_btn: string 1467 | blue_v_change_name_review_submit_btn: string 1468 | profile_personal_no_content_title: string 1469 | profile_personal_no_content_body: string 1470 | profile_no_content_title: string 1471 | profile_no_content_des: string 1472 | fc_view_empty_videos_title: string 1473 | fc_view_fav_empty_videos_desc: string 1474 | profile_public_nolikes_title: string 1475 | profile_self_public_nolikes: string 1476 | profile_others_public_nolikes: string 1477 | cancel: string 1478 | editprofile_editpage_error_photofail_others: string 1479 | editprofile_editpage_photo_editphoto: string 1480 | editprofile_editimage_zoom: string 1481 | editprofile_cancel: string 1482 | editprofile_editpage_photo_apply: string 1483 | editprofile_editpage_username_confirmtitle: string 1484 | editprofile_editpage_username_confirmtext: string 1485 | nickname_change_pop_up_title: string 1486 | nickname_change_pop_up_description: string 1487 | nickname_username_change_pop_up_title: string 1488 | nickname_username_change_pop_up_description: string 1489 | nickname_username_change_pop_up_cta_2: string 1490 | blue_v_change_username_modal_title: string 1491 | blue_v_change_username_modal_desc: string 1492 | blue_v_change_username_modal_desc_2: string 1493 | blue_v_change_name_modal_title: string 1494 | blue_v_change_name_modal_desc: string 1495 | blue_v_change_name_modal_desc_2: string 1496 | blue_v_change_username_name_modal_title: string 1497 | blue_v_webapp_change_name_modal_desc: string 1498 | blue_v_webapp_change_name_modal_desc_2: string 1499 | blue_v_change_name_modal_submit_request_btn: string 1500 | blue_v_change_name_modal_change_btn: string 1501 | blue_v_change_username_lose_badge_modal_title: string 1502 | blue_v_change_name_lose_badge_modal_title: string 1503 | blue_v_webapp_change_name_lose_badge_modal_title: string 1504 | blue_v_change_name_lose_badge_modal_desc: string 1505 | blue_v_change_name_lose_badge_confirm_btn: string 1506 | editprofile_editpage_error_row: string 1507 | editprofile_editpage_bio: string 1508 | editprofile_editpage_error_namenotavail: string 1509 | editprofile_editpage_error_max: string 1510 | editprofile_editpage_name: string 1511 | nickname_change_1st_time_description: string 1512 | nickname_change_description: string 1513 | editprofile_editpage_error_notavailable: string 1514 | editprofile_editpage_error_tryagain: string 1515 | editprofile_editpage_error_min2char: string 1516 | editprofile_editpage_error_username_max: string 1517 | editprofile_editpage_username: string 1518 | editprofile_editpage_username_subtext1: string 1519 | editprofile_editpage_username_subtext2: string 1520 | editprofile_editpage_error_photofail_max: string 1521 | editprofile_editpage_error_image_cantuse: string 1522 | editprofile_editpage_error_cantmodify_others: string 1523 | editprofile_editpage_error_cantmodify_review: string 1524 | editprofile_editpage_error_username_cantchange: string 1525 | alert_user_update_profile_limited_toast: string 1526 | account_status_banned: string 1527 | nickname_change_fail_toast: string 1528 | ecom_changename_web: string 1529 | editprofile_editprofile: string 1530 | editprofile_editpage_photo: string 1531 | editprofile_save: string 1532 | editprofile_close: string 1533 | editprofile_tooltip_title: string 1534 | editprofile_tooltip_subtitle: string 1535 | webdm_message_button: string 1536 | profile_page_message_btn: string 1537 | sug_accounts: string 1538 | profile_page_followerList_private_header: string 1539 | profile_page_followerList_private_body: string 1540 | profile_page_profile_follower_tab: string 1541 | profile_page_profile_follower_view_desc: string 1542 | profile_page_followingList_private_header: string 1543 | profile_page_followingList_private_body: string 1544 | profile_page_profile_following_tab: string 1545 | profile_page_profile_following_view_desc: string 1546 | profile_page_profile_follower_desc: string 1547 | profile_page_profile_following_desc: string 1548 | profile_page_suggested_tab: string 1549 | profile_page_profile_friends_desc: string 1550 | profile_page_friends_tab: string 1551 | user_action_unfollow: string 1552 | profile_self_link_unavailable: string 1553 | nonpersonalizedFeeds_profile_suggestedAccounts_info_body: string 1554 | nonpersonalizedFeeds_profile_suggestedAccounts_info_bodyManagePersonFeedsVariable: string 1555 | nonpersonalizedFeeds_profile_suggestedAccounts_info_bodyPrivacyVariable: string 1556 | Privacy: string 1557 | nonpersonalizedFeeds_modal_allScenarios_body_learnMore_articleLink: string 1558 | 'Learn more': string 1559 | nonpersonalizedFeeds_turnOn_modal_toggle_CTA: string 1560 | 'No bio yet.': string 1561 | Following: string 1562 | followers: string 1563 | Likes: string 1564 | playlist_webapp_profileview_btn_changeorder: string 1565 | playlist_webapp_profile_entry_create: string 1566 | playlist_webapp_changeorder_header: string 1567 | playlist_webapp_upload_nameplaylist_btn: string 1568 | playlist_webapp_profileview_playlists: string 1569 | Videos: string 1570 | LIVE: string 1571 | webLIVE_personalPage_LIVEbanner_title: string 1572 | profile_others_blocked_post_body: string 1573 | profile_others_block_post_body: string 1574 | 'This account is private': string 1575 | profile_others_private_body: string 1576 | profile_others_like_private_title: string 1577 | profile_others_like_private_body: string 1578 | pcWeb_repostTab: string 1579 | sortbyvv_profile_tab_text_favorites: string 1580 | liked: string 1581 | webLIVE_personalPage_LIVEbanner_numViewerDesc: string 1582 | webapp_profile: string 1583 | podcasts_linkFullEpisodes_publishEpisodePage_confirmationBanner: string 1584 | editprofile_toast: string 1585 | blue_v_change_name_toast_request_submitted: string 1586 | 'Page not available': string 1587 | playlist_invalid_error_code: string 1588 | videos_: string 1589 | 'No videos with this sound yet': string 1590 | webApp_effectAnchor_tryEffect: string 1591 | webApp_effectAnchor_scanModal_title: string 1592 | webApp_effectAnchor_scanModal_desc1: string 1593 | webApp_effectAnchor_scanModal_desc2: string 1594 | webApp_effectAnchor_scanModal_desc3: string 1595 | webApp_effectAnchor_createEffect: string 1596 | webApp_effectAnchor_createEffect_short: string 1597 | pcWeb_interest_dailyLife: string 1598 | pcWeb_interest_music: string 1599 | pcWeb_interest_random: string 1600 | pcWeb_interest_lipSync: string 1601 | pcWeb_interest_comics: string 1602 | pcWeb_interest_entertainment: string 1603 | pcWeb_interest_videoGames: string 1604 | pcWeb_interest_Sports: string 1605 | pcWeb_interest_comedy: string 1606 | pcWeb_interest_cosplay: string 1607 | pcWeb_interest_movies: string 1608 | pcWeb_interest_fitness: string 1609 | pcWeb_interest_romance: string 1610 | pcWeb_interest_motivational: string 1611 | pcWeb_interest_art: string 1612 | pcWeb_interest_pets: string 1613 | pcWeb_interest_beauty: string 1614 | pcWeb_interest_style: string 1615 | pcWeb_numberSelected: string 1616 | pcWeb_chooseInterest_done_btn: string 1617 | pcWeb_chooseInterest_header: string 1618 | pcWeb_chooseInterest_bodyV1: string 1619 | pcWeb_chooseInterest_bodyV2: string 1620 | pcWeb_chooseInterest_skip_btn: string 1621 | online: string 1622 | Promote_PC_popup_title: string 1623 | Promote_PC_popup_content: string 1624 | topic_foryou_topics_toast_unavailable: string 1625 | qapage_webapp_askby: string 1626 | qapage_empty_title: string 1627 | qapage_empty_desc: string 1628 | follows: string 1629 | about: string 1630 | seo_pcWeb_recipe_about_header: string 1631 | seo_pcWeb_recipe_ingredient_header: string 1632 | seo_pcWeb_recipe_step_header: string 1633 | seo_pcWeb_recipe_hint_header: string 1634 | seo_internalLink_mayBeInterested: string 1635 | seo_aggre_related_to: string 1636 | Analytics: string 1637 | Upload: string 1638 | TikTok: string 1639 | 'SEO TikTok Description': string 1640 | 'SEO TikTok Keyword': string 1641 | feedback_pc_back: string 1642 | feedback_and_help_seo_title: string 1643 | 'Is your problem resolved?': string 1644 | backend_settings_yes: string 1645 | backend_settings_no: string 1646 | backend_settings_stillhaveproblem: string 1647 | 'Help Center': string 1648 | backend_settings_topictitle: string 1649 | 'Feedback and help': string 1650 | backend_settings_faqtitle: string 1651 | 'Report a problem': string 1652 | feedback_pc_history: string 1653 | 'Tell us your feedback': string 1654 | 'Please provide as much detail as possible': string 1655 | feedback_pc_upload: string 1656 | Submit: string 1657 | 'Network error. Please try again.': string 1658 | com_mig_your_support_tickets: string 1659 | 'Description must be at least 2 characters': string 1660 | Video: string 1661 | webapp_unblocked_button1: string 1662 | webdm_block: string 1663 | webapp_privacy_and_safety_blocked_accounts: string 1664 | BA_onboarding_welcome_title: string 1665 | ttba_switch: string 1666 | ttelite_switch_title: string 1667 | ttelite_switch_intro: string 1668 | ttelite_switch_action_yes: string 1669 | ttelite_switch_action_no: string 1670 | stop_seller_remove_pop_context: string 1671 | stop_seller_remove_pop_context_hyperlink: string 1672 | stop_seller_remove_pop_title: string 1673 | manage_account: string 1674 | acc_control: string 1675 | delete_acc: string 1676 | delete_btn: string 1677 | changeRegistrationLocation_account_accountInformation: string 1678 | changeRegistrationLocation_account_accountInformation_title: string 1679 | changeRegistrationLocation_account_accountInformation_subtitle: string 1680 | Confirm: string 1681 | bc_account_private_enable_notice_content: string 1682 | bc_account_private_enable_notice_contenturl: string 1683 | ba: string 1684 | caba_no_private: string 1685 | caba_no_private_desc: string 1686 | private_acc_ads: string 1687 | switch_public_h1: string 1688 | switch_public_desc: string 1689 | bc_account_private_enable_notice_title: string 1690 | disallowSwitchAccount_privacy_popUp_title: string 1691 | disallowSwitchAccount_privacy_popUp_description: string 1692 | disallowSwitchAccount_privacy_popUp_placeholder: string 1693 | disallowSwitchAccount_privacy_popUp_placeholder2: string 1694 | disallowSwitchAccount_privacy_popUp_button2: string 1695 | toast_restricted_fam_pairing: string 1696 | privacy_h1: string 1697 | discoverability: string 1698 | private_acc: string 1699 | private_acc_desc: string 1700 | feedback_webform_dropdown_tt4b_opt_2: string 1701 | download_data_entry_point: string 1702 | datadownload_process_download_your_data: string 1703 | dyd_desc: string 1704 | ok_btn: string 1705 | privacy: string 1706 | Language: string 1707 | datadownload_screentitle: string 1708 | 'Privacy and settings': string 1709 | WebApp_coin_recharge_1: string 1710 | desktop_push_turn_on_tips_text1: string 1711 | accessibilityLabels_settings_pushNotifs_modal_lockIcon: string 1712 | desktop_push_turn_on_tips_text2: string 1713 | push_notifications: string 1714 | desktop_notifications: string 1715 | allow_in_browser: string 1716 | desktop_push_tips: string 1717 | desktop_push_turn_on_tips_title: string 1718 | push_preferences: string 1719 | push_preferences_tips: string 1720 | interactions: string 1721 | push_likes_description: string 1722 | push_likes: string 1723 | push_comments: string 1724 | push_new_followers: string 1725 | push_mentions: string 1726 | screentimedash_digitalwellbeing_summary_timespent_graph_yaxis_hours_1: string 1727 | screentimedash_digitalwellbeing_summary_timespent_graph_yaxis_minutes_1: string 1728 | screentimedash_digitalwellbeing_summary_day_label_sun: string 1729 | screentimedash_digitalwellbeing_summary_day_label_mon: string 1730 | screentimedash_digitalwellbeing_summary_day_label_tue: string 1731 | screentimedash_digitalwellbeing_summary_day_label_wed: string 1732 | screentimedash_digitalwellbeing_summary_day_label_thu: string 1733 | screentimedash_digitalwellbeing_summary_day_label_fri: string 1734 | screentimedash_digitalwellbeing_summary_day_label_sat: string 1735 | screentimedash_digitalwellbeing_summary_month_label_jan: string 1736 | screentimedash_digitalwellbeing_summary_month_label_feb: string 1737 | screentimedash_digitalwellbeing_summary_month_label_mar: string 1738 | screentimedash_digitalwellbeing_summary_month_label_apr: string 1739 | screentimedash_digitalwellbeing_summary_month_label_may: string 1740 | screentimedash_digitalwellbeing_summary_month_label_jun: string 1741 | screentimedash_digitalwellbeing_summary_month_label_jul: string 1742 | screentimedash_digitalwellbeing_summary_month_label_aug: string 1743 | screentimedash_digitalwellbeing_summary_month_label_sep: string 1744 | screentimedash_digitalwellbeing_summary_month_label_oct: string 1745 | screentimedash_digitalwellbeing_summary_month_label_nov: string 1746 | screentimedash_digitalwellbeing_summary_month_label_dec: string 1747 | screentimedash_digitalwellbeing_summary_timespent_day: string 1748 | screentimedash_digitalwellbeing_summary_timespent_hours_1: string 1749 | screentimedash_digitalwellbeing_summary_timespent_minutes_1: string 1750 | screentimedash_digitalwellbeing_summary_timespent_night: string 1751 | screentimedash_digitalwellbeing_summary_appopened_day_1: string 1752 | screentimedash_digitalwellbeing_summary_appopened_night_1: string 1753 | screentimedash_digitalwellbeing_summary_appopened_actionsheet_chooseweek_title: string 1754 | screentimedash_digitalwellbeing_summary_timespent_tab: string 1755 | screentimedash_digitalwellbeing_summary_appopened_tab: string 1756 | screentimedash_digitalwellbeing_summary_timespent_header_daytime: string 1757 | screentimedash_digitalwellbeing_summary_daytime_tip_desc: string 1758 | screentimedash_digitalwellbeing_summary_nighttime_tip_title: string 1759 | screentimedash_digitalwellbeing_summary_nighttime_tip_desc: string 1760 | screentimedash_digitalwellbeing_summary_appopened_header_total: string 1761 | screentime_settings_dailyscreentime_status_off: string 1762 | screentime_settings_title: string 1763 | screenTime_web_infoIcon_desc: string 1764 | screentimedash_digitalwellbeing_dailyscreentime_title: string 1765 | screentime_settings_screentimebreaks_title: string 1766 | screentime_settings_screentimebreaks_desc: string 1767 | nightscreentimemgmt_screentimesettings_sleepreminders_feature_name: string 1768 | nightscreentimemgmt_screentimesettings_sleepreminders_feature_desc: string 1769 | screentimedash_digitalwellbeing_weeklyscreentime_title: string 1770 | screentimedash_digitalwellbeing_weeklyscreentime_desc: string 1771 | screentimedash_digitalwellbeing_summary_header: string 1772 | screenTime_summarySection_desc: string 1773 | teenScreenTimeDashboard_familyPairing_header_helpAndResources: string 1774 | teenScreenTimeDashboard_familyPairing_screenTime_link: string 1775 | pa_ads_label: string 1776 | customizeSTM_screenTimeLimit_selectTime_minutes: string 1777 | customizeSTM_screenTimeLimit_selectTimeActionSheet: string 1778 | customizeSTM_screenTimeLimit_selectTime_hours: string 1779 | customizeSTM_dailyScreenTimeOn_header_notified: string 1780 | customizeSTM_dailyScreenTimeOn_desc_notified: string 1781 | customizeSTM_dailyScreenTimeOn_header_discuss: string 1782 | customizeSTM_dailyScreenTimeOn_desc_discuss: string 1783 | customizeSTM_dailyScreenTimeOn_header_time_minutes: string 1784 | customizeSTM_dailyScreenTimeOn_header_time_hours: string 1785 | customizeSTM_dailyScreenTimeOn_header_time_hoursMinutes: string 1786 | customizeSTM_teenDailyScreenTimeOn_header: string 1787 | customizeSTM_dailyScreenTimeOn_title: string 1788 | customizeSTM_dailyScreenTimeOff_title: string 1789 | dailyscreentime_featurescreen_heading: string 1790 | SEO_setting_title: string 1791 | Sub_emote_goback: string 1792 | webapp_block_experience_unblock_popup_header: string 1793 | webapp_block_experience_block_popup_header: string 1794 | webapp_block_experience_unblock_popup_body: string 1795 | webapp_block_experience_block_popup_body: string 1796 | webapp_unblocked_button2: string 1797 | unblock: string 1798 | video_detail: string 1799 | creator: string 1800 | video_details_page_comment_header: string 1801 | ad_comment_close_des: string 1802 | scheduled_video_comment_unavailable: string 1803 | Close: string 1804 | asr_transcript_onpc_kebab_menu_ab_transcript_button: string 1805 | cc_webapp_age_video_details_title: string 1806 | classifyV1AWeb_webAppDesktop_maskLayer_headerTitle: string 1807 | cc_webapp_age_video_details_body: string 1808 | classifyV1AWeb_webAppDesktop_maskLayer_button: string 1809 | pcWeb_floatingPlayer_on: string 1810 | pcWeb_multitaskPlayer_on: string 1811 | pcWeb_miniPlayer_turnOff_cta: string 1812 | ad_not_support: string 1813 | profile_page_pin: string 1814 | video_details_page_morevideos_btn: string 1815 | 'Log In': string 1816 | pc_web_you_may_like: string 1817 | "Couldn't upload image. Please try again": string 1818 | setting_feedback_delete_picture: string 1819 | setting_feedback_delete_history: string 1820 | basicPoi_moreRelated: string 1821 | no_video_in_collection_error_title: string 1822 | no_video_in_collection_error_description: string 1823 | collection_not_availble_error: string 1824 | shared_collection_dmcard_title: string 1825 | shared_collection_dmcard_desc: string 1826 | support_webapp_sharing_chat_page_video_card_3: string 1827 | Feedback: string 1828 | support_webapp_sharing_chat_page_video_card_1: string 1829 | support_webapp_sharing_chat_page_video_card_2: string 1830 | photo_post_unavailable_title: string 1831 | subVideo_unavailableScreen_title: string 1832 | dm_stranger_delete_this_message_header: string 1833 | dm_stranger_delete_this_message_body: string 1834 | dm_tcm_request_link_report: string 1835 | dm_message_request_report: string 1836 | dm_tcm_request_desc_business_wants_send_msg: string 1837 | dm_message_request: string 1838 | dm_tcm_request_title_business_wants_send_msg: string 1839 | dm_message_request_title: string 1840 | dm_delete: string 1841 | dm_accept: string 1842 | webdm_unblock_this_account: string 1843 | webdm_inputbox_block_note: string 1844 | im_hint_send_msg: string 1845 | comment_tray_emoji: string 1846 | subVideo_nonsubs_webToast: string 1847 | dm_tcm_card_title_business_invitation: string 1848 | webdm_message_not_supported: string 1849 | direct_meaasge_sending_ban_feedback: string 1850 | direct_meaasge_sending_ban_notice: string 1851 | webdm_unlike: string 1852 | Like: string 1853 | webdm_report: string 1854 | Friends: string 1855 | Inbox_Follow_back: string 1856 | dm_tcm_banner_from_tcm: string 1857 | WBS_inbox_cc_view: string 1858 | wbs_inbox_msg_cctos_createcontacts: string 1859 | webdm_report_01_message_selected: string 1860 | webdm_report_n_message_selected: string 1861 | Back: string 1862 | Report_reason: string 1863 | dm_web_baLabel_filter: string 1864 | dm_web_baLabel_emptyLabel_state: string 1865 | dm_web_baLabel_apply_btn: string 1866 | dm_web_baLabel_unreadOnly_checkbox: string 1867 | privacy_and_safety_message_detail: string 1868 | setting_disabled_16: string 1869 | hint_dm_settings: string 1870 | option_everyone: string 1871 | option_friends: string 1872 | option_no_one: string 1873 | family_pairing_toast_parent_settings: string 1874 | webdm_message_settings: string 1875 | dm_who_can_send_you_direct_messages: string 1876 | dm_tcm_section_name_msg_preferences: string 1877 | dm_tcm_toggle_title_always_allow: string 1878 | dm_tcm_toggle_desc_tcm: string 1879 | webdm_cancel: string 1880 | save_settings: string 1881 | message_request_inbox: string 1882 | webdm_chatlist_head_messages: string 1883 | like_message: string 1884 | dm_multiple_messages: string 1885 | support_webapp_sharing_chat_page_status_2: string 1886 | support_webapp_sharing_chat_page_status_1: string 1887 | dm_left_swipe_unmute: string 1888 | dm_left_swipe_mute: string 1889 | no_top: string 1890 | webdm_pin_to_top: string 1891 | dm_tcm_label_business: string 1892 | dm_web_baLabel_noChatFound_header: string 1893 | dm_web_baLabel_noChatFound_body: string 1894 | im_message_list_empty: string 1895 | webdm_report_type: string 1896 | webdm_report_why: string 1897 | webdm_next: string 1898 | webdm_report_popup_title: string 1899 | webdm_report_popup_detail: string 1900 | webdm_done: string 1901 | dm_stranger_error_message_header: string 1902 | dm_stranger_error_message_body: string 1903 | SEO_dm_title: string 1904 | playlist_webapp_profileView_error_header: string 1905 | playlist_webapp_profileView_error_desc: string 1906 | playlist_webapp_toast_deleted: string 1907 | playlist_webapp_profileview_btn_editname: string 1908 | playlist_webapp_profileview_btn_deleteplaylist: string 1909 | playlist_webapp_editname_header: string 1910 | playlist_webapp_deleteplaylist_header: string 1911 | playlist_webapp_editname_desc: string 1912 | playlist_webapp_deleteplaylist_desc: string 1913 | playlist_webapp_deleteplaylist_btn_cancel: string 1914 | playlist_webapp_editname_btn: string 1915 | playlist_webapp_deleteplaylist_btn_delete: string 1916 | playlist_webapp_profileview_btn_removevid: string 1917 | playlist_webapp_profileview_btn_addvid: string 1918 | login_fb_noLonger_title: string 1919 | login_fb_noLonger_body: string 1920 | login_fb_noLonger_cta1: string 1921 | login_fb_noLonger_cta2: string 1922 | comment_tray_reply_default: string 1923 | pcWeb_add_reply: string 1924 | comment_tray_default: string 1925 | pc_web_explorePage_topics_singing_dancing: string 1926 | pc_web_explorePage_topics_comedy: string 1927 | pc_web_explorePage_topics_sports: string 1928 | pc_web_explorePage_topics_anime_comics: string 1929 | pc_web_explorePage_topics_relationship: string 1930 | pc_web_explorePage_topics_shows: string 1931 | pc_web_explorePage_topics_lipsync: string 1932 | pc_web_explorePage_topics_daily_life: string 1933 | pc_web_explorePage_topics_beauty_care: string 1934 | pc_web_explorePage_topics_games: string 1935 | pc_web_explorePage_topics_society: string 1936 | pc_web_explorePage_topics_outfit: string 1937 | pc_web_explorePage_topics_cars: string 1938 | pc_web_explorePage_topics_food: string 1939 | pc_web_explorePage_topics_animals: string 1940 | pc_web_explorePage_topics_family: string 1941 | pc_web_explorePage_topics_drama: string 1942 | pc_web_explorePage_topics_fitness_health: string 1943 | pc_web_explorePage_topics_education: string 1944 | pc_web_explorePage_topics_technology: string 1945 | pc_web_empty_state_novid_header: string 1946 | pc_web_empty_state_novid_body: string 1947 | pc_web_explorePage_all: string 1948 | pcWeb_seasonal_tab_newYear: string 1949 | pcWeb_seasonal_tab_christmas: string 1950 | pc_web_explore_meta_title: string 1951 | pc_web_explore_meta_desc: string 1952 | pcWeb_survey_popup_header: string 1953 | pcWeb_survey_popup_body: string 1954 | pcWeb_survey_popup_cta1: string 1955 | pcWeb_survey_popup_cta2: string 1956 | feed: string 1957 | custom: string 1958 | website: string 1959 | ttlive_webLIVE_LIVEpreview_survey_q1: string 1960 | ttlive_webLIVE_LIVEpreview_survey_a1_1: string 1961 | ttlive_webLIVE_LIVEpreview_survey_a1_2: string 1962 | ttlive_webLIVE_LIVEpreview_survey_a1_3: string 1963 | ttlive_webLIVE_LIVEpreview_survey_q2: string 1964 | ttlive_webLIVE_LIVEpreview_survey_a2_1: string 1965 | ttlive_webLIVE_LIVEpreview_survey_a2_2: string 1966 | ttlive_webLIVE_LIVEpreview_survey_a2_3: string 1967 | ttlive_webLIVE_LIVEpreview_surveySubmitted_toast: string 1968 | Next: string 1969 | seo_popular_faq: string 1970 | keys: string 1971 | embed: string 1972 | account: string 1973 | update: string 1974 | net: string 1975 | ca: string 1976 | Required: string 1977 | subLiveShare_webLivePage_chatTextfield_subOnlyNote: string 1978 | Webapp_tooltips_Pause: string 1979 | Webapp_tooltips_play: string 1980 | pm_web_fullpage_entry: string 1981 | pm_web_fullpage_error_button: string 1982 | live_error_network_title: string 1983 | live_error_network_body: string 1984 | live_error_network_button: string 1985 | live_ending_title: string 1986 | pm_mt_livecard_end_subtitle_1: string 1987 | pm_web_fyp_homePage_entry: string 1988 | live_watching_toast_host_away: string 1989 | pm_mt_multiguest_enlarge_host_tag: string 1990 | webapp_forYoufeed_notInterested_btn: string 1991 | about_this_ad_title: string 1992 | Copied: string 1993 | copy_link: string 1994 | webapp_share_btn: string 1995 | accessibilityLabels_forYou_btn_share: string 1996 | fixed_likes: string 1997 | comment_tray_exit_title: string 1998 | comment_tray_exit_des: string 1999 | comment_tray_exit_leave: string 2000 | comment_tray_exit_stay: string 2001 | pcWeb_login_browserMode: string 2002 | webapp_seekbar_tooltip: string 2003 | pc_web_browser_creatorVid_exit: string 2004 | pc_web_volume_btn: string 2005 | view_analytics: string 2006 | deleted: string 2007 | video_unavailable_deleted: string 2008 | comment_turnoff_unlike: string 2009 | comment_turnoff_like: string 2010 | comment_nointernet_toast: string 2011 | comment_delete_success: string 2012 | comment_delete_failed: string 2013 | report_Prohibited_or_infringing: string 2014 | report_Right_owner: string 2015 | report_Prohibited_or_violence: string 2016 | report_Not_right_owner: string 2017 | Web_report_thanks_for_report: string 2018 | dsa_illegal_report_received_confirm_logout: string 2019 | dsa_illegal_report_received_confirm: string 2020 | pm_mt_live_done: string 2021 | Web_report_report_for_error: string 2022 | live_close: string 2023 | pm_mt_live_page_sth_wrong: string 2024 | pm_mt_live_page_try_again: string 2025 | report_inbox_retry_btn: string 2026 | 'Please select a scenario': string 2027 | Web_report_reason_select: string 2028 | dsa_illegal_placeholder_learnmore: string 2029 | Web_report_description: string 2030 | report_details_toast: string 2031 | attachment_upload_limit: string 2032 | report_img_toast: string 2033 | event_dm_share_message_card: string 2034 | pcWeb_youReposted_label: string 2035 | pcWeb_nickReposted_label: string 2036 | qapage_webapp_error_title: string 2037 | subVideo_viewing_lable: string 2038 | Web_report_hide_video: string 2039 | Web_report_show_video: string 2040 | scheduled_for: string 2041 | pc_web_playing_now: string 2042 | pc_web_fullscreen_btn: string 2043 | pc_web_speed_btn: string 2044 | who_can_view_public: string 2045 | public_desc: string 2046 | who_can_view_followers: string 2047 | followers_desc_for_private: string 2048 | who_can_view_friends: string 2049 | followers_desc: string 2050 | private_desc: string 2051 | commonStrings_privacySettings_option_friends: string 2052 | commonStrings_privacySettings_optionDescription_friends: string 2053 | commonStrings_privacySettings_option_onlyYou: string 2054 | commonStrings_privacySettings_option_everyone: string 2055 | commonStrings_privacySettings_option_onOffTikTok: string 2056 | useAlignedCopies_privacySettings_panel_description: string 2057 | new_video_status: string 2058 | pull_video_expl_available_for_ads: string 2059 | duet_stitch_minor: string 2060 | hint2: string 2061 | hint1: string 2062 | privacy_set: string 2063 | view_access: string 2064 | allow_comment: string 2065 | allow_duet: string 2066 | allow_stitch: string 2067 | privacy_settings_done: string 2068 | delete_confirm: string 2069 | cancel_settings: string 2070 | comment_at_search: string 2071 | comment_at_load: string 2072 | comment_at_tryagain: string 2073 | no_at_me: string 2074 | mention_privacy_toast_cant_mention: string 2075 | comment_tray_at: string 2076 | comment_tray_btn: string 2077 | comment_reply_success: string 2078 | comment_post_success: string 2079 | comment_banned_toast: string 2080 | comment_post_failed: string 2081 | searchquerycomment_feedbackpanel_notinterested: string 2082 | searchquerycomment_feedbackpanel_unrelated: string 2083 | searchquerycomment_feedbackpanel_inappropriate: string 2084 | searchquerycomment_feedbackpanel_others: string 2085 | comment_delete_cancel: string 2086 | searchquerycomment_feedbackpanel_header: string 2087 | accessibilityLabels_forYou_btn_like: string 2088 | comment_delete_btn: string 2089 | comment_delete_des: string 2090 | comment_delete_confirm: string 2091 | following_acc: string 2092 | friends_acc: string 2093 | WebApp_comment_copyurl_id: string 2094 | comment_reply_btn: string 2095 | hide: string 2096 | pcWeb_detailPage_comment_viewNumReply: string 2097 | pcWeb_detailPage_comment_viewNumMore: string 2098 | view_more_replies: string 2099 | comment_panel_zero: string 2100 | Comment: string 2101 | pc_web_previous_btn: string 2102 | pc_web_next_btn: string 2103 | pc_web_login: string 2104 | pc_web_login_to_comment: string 2105 | pcWeb_detailPage_backTop_btn: string 2106 | pc_web_browser_nowPlaying: string 2107 | fixed_comments: string 2108 | pc_web_browser_tabName_creatorVid: string 2109 | support_webapp_sharing_error_message: string 2110 | support_webapp_sharing_sent_toast_1: string 2111 | support_webapp_sharing_sent_toast_2: string 2112 | support_webapp_sharing_sent_toast_3: string 2113 | support_webapp_sharing_option_button: string 2114 | support_webapp_sharing_toast_2: string 2115 | support_webapp_sharing_toast_1: string 2116 | subVideo_share_note: string 2117 | support_webapp_sharing_searchbar_ghosttext: string 2118 | support_webapp_sharing_search_results: string 2119 | support_webapp_sharing_recent: string 2120 | support_webapp_sharing_following: string 2121 | support_webapp_sharing_write_a_message: string 2122 | support_webapp_sharing_send_button: string 2123 | pcWeb_NewFeatureFloating: string 2124 | creatorCenter_createVideosCapCutOnline_banner_btn1: string 2125 | pcWeb_Floating: string 2126 | pcWeb_Multitask: string 2127 | embed_profile_popup_title: string 2128 | embed_profile_popup_desc: string 2129 | embeds_popup_hashtag_header: string 2130 | embeds_popup_hashtag_body: string 2131 | embeds_popup_sound_header: string 2132 | embeds_popup_sound_body: string 2133 | 'Embed video': string 2134 | embed_popup_embed_body: string 2135 | embeds_popup_tns: string 2136 | embed_profile_popup_bottom_desc_tos: string 2137 | embed_profile_card_desc_privacy_policy: string 2138 | 'By embedding this video, you confirm that you agree to our Terms of Use and acknowledge you have read and understood our Privacy Policy.': string 2139 | embed_profile_popup_btn: string 2140 | web_sharing_disable_toast: string 2141 | embed_success: string 2142 | embed_profile_tooltip: string 2143 | accessibilityLabels_forYou_share_moreOptions_btn: string 2144 | masklayer_general_title: string 2145 | photosensitive_masklayer_title: string 2146 | photosensitive_masklayer_removed: string 2147 | masklayer_general_body: string 2148 | photosensitive_masklayer_body1: string 2149 | photosensitive_masklayer_body2: string 2150 | photosensitive_masklayer_removed_body1: string 2151 | photosensitive_masklayer_removed_body3: string 2152 | masklayer_general_skip: string 2153 | photosensitive_masklayer_watch: string 2154 | masklayer_general_watch: string 2155 | photosensitive_masklayer_skipall: string 2156 | seo_popular_disclaimer: string 2157 | seo_popular_disclaimer2_btn: string 2158 | bc_likes: string 2159 | bc_comments: string 2160 | bc_shares: string 2161 | seo_aggre_see_more: string 2162 | seo_aggre_transcript_header: string 2163 | get_app: string 2164 | get_tt_desktop: string 2165 | get_tt_app: string 2166 | accessibilityLabels_forYou_scroll_btn: string 2167 | webapp_feed_redesign_zerovideo: string 2168 | webapp_feed_redesign_retry: string 2169 | send_message: string 2170 | creatorCenter_content_actions: string 2171 | home_error_video_geofencing: string 2172 | music_detail_unavailable_2: string 2173 | qapage_webapp_error_subtitle: string 2174 | photo_post_unavailable_dec: string 2175 | disable_reuse_soundtrack_unavailable_page_body: string 2176 | poisharing_edgecase_one: string 2177 | poistore_detail_text: string 2178 | qa_reflow_page_empty_subtitle: string 2179 | ext_share_story_viewmore_btn: string 2180 | poisharing_cta_return: string 2181 | "Couldn't find this account": string 2182 | "Couldn't find this sound": string 2183 | disable_reuse_soundtrack_unavailable_mobile_body: string 2184 | embed_err_unavailable: string 2185 | "Couldn't find this hashtag": string 2186 | desktop_error_video_geofencing: string 2187 | qa_page_reflow_page_blank_title: string 2188 | poisuggest_placeuna_title_1: string 2189 | err_feature_unavailable: string 2190 | playlist_unavailable: string 2191 | accessibilityLabels_forYou_videoCard_fullScreen: string 2192 | cover_notice_violation: string 2193 | official_tag: string 2194 | original_tag: string 2195 | seo_user_video_cover: string 2196 | or: string 2197 | playlist_webapp_creation_namePlaylist_characterCount_limit: string 2198 | yproject_playlist_name_toast: string 2199 | playlist_webapp_upload_nameplaylist_header: string 2200 | playlist_webapp_toast_error_vidlimit: string 2201 | playlist_webapp_selectvid_error_header: string 2202 | playlist_webapp_selectvid_error_desc: string 2203 | playlist_webapp_selectvid_header: string 2204 | playlist_webapp_selectvid_desc: string 2205 | playlist_webapp_selectvid_toast_alreadyadded: string 2206 | playlist_webapp_toast_error_cheatPlaylistCannotAdd: string 2207 | playlist_webapp_profileview_toast_vidremoved: string 2208 | Expand: string 2209 | basicPoi_relatedTopics: string 2210 | pc_web_playpause_btn: string 2211 | pc_web_skip_forward_5_sec_btn: string 2212 | pc_web_skip_back_5_sec_btn: string 2213 | pc_web_muteunmute_btn: string 2214 | desktop_kb_shortcuts_tooltip_previous: string 2215 | desktop_kb_shortcuts_tooltip_next: string 2216 | accessibilityLabels_forYou_videoControls_videoProgress: string 2217 | accessibilityLabels_feed_icon_favorite: string 2218 | accessibilityLabels_forYou_btn_comment: string 2219 | accessibilityLabels_forYou_videoControls_volume_btn: string 2220 | accessibilityLabels_forYou_videoControls_report_btn: string 2221 | comments: string 2222 | accessibilityLabels_forYou_videoControls_pause_btn: string 2223 | accessibilityLabels_forYou_videoControls_play_btn: string 2224 | pcWeb_firstTime_expand2_guide: string 2225 | Download: string 2226 | Caption: string 2227 | Open: string 2228 | start_time: string 2229 | load_error: string 2230 | discard: string 2231 | more: string 2232 | post_now: string 2233 | Follow: string 2234 | settings: string 2235 | end_live: string 2236 | follow: string 2237 | see_all: string 2238 | see_less: string 2239 | go_live: string 2240 | upload_fail: string 2241 | Search: string 2242 | inbox: string 2243 | select_file: string 2244 | email_redesign_webapp_order_details_page_title: string 2245 | email_redesign_webapp_logistics_page_title: string 2246 | email_redesign_webapp_write_review_page_title: string 2247 | email_redesign_webapp_refund_detail_page_title: string 2248 | email_redesign_webapp_orders_title: string 2249 | email_redesign_webapp_vouchers_title: string 2250 | email_redesign_webapp_shopping_cart_title: string 2251 | seller_messages_email_webapp_reply_title: string 2252 | seller_messages_email_webapp_mute_title: string 2253 | seller_messages_email_webapp_setting_title: string 2254 | Ecom_email_pc_shoptab_homepage_title: string 2255 | Ecom_email_pc_pdp_shoptab_homepage_title: string 2256 | Ecom_email_pc_deal_page_shoptab_homepage_title: string 2257 | Ecom_email_pc_pdp_title: string 2258 | Ecom_email_pc_coupon_add_on_title: string 2259 | Ecom_email_pc_free_shipping_add_on_page_title: string 2260 | email_redesign_webapp_order_details_page_context: string 2261 | email_redesign_webapp_logistics_page_context: string 2262 | email_redesign_webapp_write_review_page_context: string 2263 | email_redesign_webapp_refund_detail_page_context: string 2264 | email_redesign_webapp_orders_context: string 2265 | email_redesign_webapp_vouchers_context: string 2266 | email_redesign_webapp_shopping_cart_context: string 2267 | seller_messages_email_webapp_reply_desc: string 2268 | seller_messages_email_webapp_mute_desc: string 2269 | seller_messages_email_webapp_setting_desc: string 2270 | Ecom_email_pc_shoptab_homepage_description: string 2271 | Ecom_email_pc_pdp_shoptab_homepage_description: string 2272 | Ecom_email_pc_deal_page_shoptab_homepage_description: string 2273 | Ecom_email_pc_pdp_description: string 2274 | Ecom_email_pc_coupon_add_on_description: string 2275 | Ecom_email_pc_free_shipping_add_on_page_description: string 2276 | terms: string 2277 | copyright: string 2278 | Legal: string 2279 | 'Privacy Policy': string 2280 | help: string 2281 | safety: string 2282 | privacyCenter_webFooter_resourcesPrivacy_navLink: string 2283 | 'Community Guidelines': string 2284 | hca_web_Company: string 2285 | hca_web_Program: string 2286 | hca_web_TermsAndPolicies: string 2287 | auto_play: string 2288 | for_you: string 2289 | 'TikTok i18n title': string 2290 | accessibilityLabels_forYou_nav_tiktok_btn: string 2291 | following_my_empty_desc: string 2292 | followers_my_empty_desc: string 2293 | common_registration_username_suggested: string 2294 | profile_suggested_empty_toast: string 2295 | feed_caption_see_more: string 2296 | desktop_logged_in_profile: string 2297 | sidenav_follow_hint: string 2298 | Discover: string 2299 | tteh_webapp_acquisitionBanner_1: string 2300 | tteh_webapp_acquisitionBanner_2: string 2301 | hca_web_Channels: string 2302 | pm_mt_obs_revoke_desc: string 2303 | pm_mt_revoke_duration: string 2304 | pm_mt_modal_revoke_confirm_btn: string 2305 | webLIVE_enableEvent_LIVEPage_eventStartNowReminder: string 2306 | webLIVE_enableEvent_LIVEPage_eventReminder: string 2307 | live_on_status: string 2308 | sidenav_login_cta: string 2309 | pc_web_explore_main_header: string 2310 | Profile: string 2311 | nonpersonalizedFeeds_LIVEfeed_navP_menuLink: string 2312 | pc_web_column_mode_tooltip: string 2313 | pc_web_browser_mode_btn: string 2314 | pc_web_column_mode_btn: string 2315 | privateAccountPrompt_manageAccount_privateAccount_title: string 2316 | privateAccountPrompt_account_permission_current_label: string 2317 | privateAccountPrompt_manageAccount_privateAccount_body: string 2318 | privateAccountPrompt_manageAccount_publicAccount_title: string 2319 | privateAccountPrompt_manageAccount_publicAccount_body2: string 2320 | privateAccountPrompt_stayPrivate_button: string 2321 | privateAccountPrompt_stayPublic_button: string 2322 | privateAccountPrompt_manageAccount_privateAccount_button2: string 2323 | privateAccountPrompt_switchPrivate_button: string 2324 | privateAccountPrompt_switchPublic_button: string 2325 | privateAccountPrompt_manageAccount_privateAccount_button3: string 2326 | privateAccountPrompt_manageAccount_privateAccount_button4: string 2327 | privateAccountPrompt_manageAccount_title: string 2328 | privateAccountPrompt_popUp_prompt_title: string 2329 | privateAccountPrompt_welcomePage_title: string 2330 | privateAccountPrompt_manageAccount_privateAccount_description3: string 2331 | privateAccountPrompt_popUp_prompt_description: string 2332 | privateAccountPrompt_account_permission_disclaimer: string 2333 | privateAccountPrompt_manageAccount_privateAccount_placeholder: string 2334 | pcWeb_miniPlayer_linkOpened_toast: string 2335 | pcWeb_miniPlayer_backToLogIn_toast: string 2336 | pcWeb_miniPlayer_linkCopied_toast: string 2337 | pcWeb_videoSkipped: string 2338 | pcWeb_NotSupportedFloating: string 2339 | pcWeb_NotSupportedMulti: string 2340 | TTweb_fyf_menuDownloadVideo_menuLink: string 2341 | TTweb_fyf_menuSendtoFriend_menuLink: string 2342 | TTweb_fyf_menuPictureinPicture_menuLink: string 2343 | changeRegistrationLocation_weakWarning_loseFeatures_toast: string 2344 | settings_privacy_interactions_comment: string 2345 | nonpersonalizedFeeds_feed_entrypoint_manageFeed: string 2346 | webAnalytics_videoDetail_viewPerformance: string 2347 | expansion_SEO_Vp: string 2348 | ls_view_details: string 2349 | webapp_mig_blocked: string 2350 | webapp_mig_unblocked: string 2351 | vid_mod_analytics_penalty_reason_minor_title: string 2352 | vid_mod_analytics_penalty_reason_minor_desc: string 2353 | vid_mod_analytics_penalty_reason_unoriginal_title: string 2354 | vid_mod_analytics_penalty_reason_unoriginal_desc: string 2355 | vid_mod_analytics_nr_vid_penalty_reason_unoriginal_title: string 2356 | vid_mod_analytics_nr_vid_penalty_reason_unoriginal_desc: string 2357 | vid_mod_analytics_nr_acct_penalty_reason_unoriginal_title: string 2358 | vid_mod_analytics_nr_acct_penalty_reason_unoriginal_desc: string 2359 | vid_mod_analytics_penalty_reason_spam_title: string 2360 | vid_mod_analytics_penalty_reason_spam_desc: string 2361 | vid_mod_analytics_penalty_reason_sexual_title: string 2362 | vid_mod_analytics_penalty_reason_sexual_desc: string 2363 | vid_mod_analytics_penalty_reason_tobacco_title: string 2364 | vid_mod_analytics_penalty_reason_tobacco_desc: string 2365 | vid_mod_analytics_penalty_reason_stunts_title: string 2366 | vid_mod_analytics_penalty_reason_stunts_desc: string 2367 | vid_mod_analytics_penalty_reason_graphic_title: string 2368 | vid_mod_analytics_penalty_reason_graphic_desc: string 2369 | vid_mod_analytics_penalty_reason_fyf_title: string 2370 | vid_mod_analytics_penalty_reason_fyf_desc: string 2371 | vidModAnalytics_detailPg_sectionHumanMod_sectionBody: string 2372 | vidModAnalytics_detailPg_sectionVideoDetails_sectionLabel: string 2373 | vidModAnalytics_detailPg_sectionDatePosted_sectionLabel: string 2374 | vid_mod_analytics_appeal_detailpg_reason_title: string 2375 | vid_mod_analytics_detail_pg_title: string 2376 | vid_mod_analytics_detail_pg_desc: string 2377 | vidModAnalytics_detailPg_sectionSuccess_header: string 2378 | vid_mod_analytics_appeal_success_detail_pg_desc: string 2379 | vid_mod_analytics_appeal_detail_pg_title: string 2380 | vid_mod_analytics_appeal_detail_pg_desc: string 2381 | vidModAnalytics_appealSubmitted_sectionTitle_header: string 2382 | vid_mod_analytics_appeal_rcv_detail_pg_desc: string 2383 | dsa_illegal_appeal_expired_header: string 2384 | dsa_illegal_appeal_expired_desc: string 2385 | dsa_illegal_appeal_button_ok: string 2386 | dsaCGWebapp_detailPg_sectionCG_body: string 2387 | dsaCGWebapp_detailPg_sectionCG_link: string 2388 | dsaCGWebapp_appealExpired_emptyState_body: string 2389 | appeal_btn_new: string 2390 | dsa_illegal_appeal_dropdown_title: string 2391 | dsa_illegal_appeal_explanation: string 2392 | dsa_illegal_appeal_alt_options: string 2393 | inbox_all_activity: string 2394 | system_notifications_inbox_channel_name_accountupdates: string 2395 | system_notifications_inbox_channel_name_tiktok: string 2396 | system_notifications_inbox_channel_name_creatormonetization: string 2397 | system_notifications_inbox_channel_name_adssupport: string 2398 | system_notifications_inbox_channel_name_businessaccount: string 2399 | promote_title: string 2400 | TTweb_inbox_systemNotificationchannel_brandActivity_name: string 2401 | TTweb_inbox_systemNotificationchannel_tiktokPlatform_name: string 2402 | TTweb_inbox_systemNotificationchannel_adsFeedback_name: string 2403 | TTweb_inbox_systemNotificationchannel_missions_name: string 2404 | system_notifications_inbox_channel_name_transactionassistant: string 2405 | TTweb_inbox_systemNotificationchannel_creatorProgram_name: string 2406 | system_notifications_inbox_channel_name_live: string 2407 | TTweb_inbox_systemNotificationchannel_screenTime_name: string 2408 | TTweb_inbox_systemNotificationchannel_mlbb_name: string 2409 | TTweb_inbox_systemNotificationchannel_series_name: string 2410 | TTweb_inbox_systemNotificationchannel_creatorMarketplace_name: string 2411 | TTweb_inbox_systemNotificationchannel_effects_name: string 2412 | report_inbox_status: string 2413 | report_inbox_inreview: string 2414 | report_inbox_violation: string 2415 | report_inbox_noviolation: string 2416 | dsa_report_pg_header: string 2417 | dsa_illegal_report_inbox_resubmit: string 2418 | tiktok_series_appeal_request_review_series_details_title: string 2419 | dailyscreentime_notifreminder_desc_minutes: string 2420 | familyPairing_dailyScreenTime_intervention_desc_minutes: string 2421 | dailyscreentime_notifreminder_desc_hours: string 2422 | familyPairing_dailyScreenTime_intervention_desc_hours: string 2423 | familyPairing_dailyScreenTime_intervention_desc_hoursMinutes: string 2424 | dailyscreentime_notifreminder_toast_incorrectpasscode: string 2425 | nightscreentimemgmt_sleepreminders_modal_readyforsleep_heading: string 2426 | nightscreentimemgmt_sleepreminders_modal_readyforsleep_firstreminder_desc: string 2427 | nightscreentimemgmt_sleepreminders_modal_readyforsleep_editreminder_link: string 2428 | nightscreentimemgmt_sleepreminders_modal_readyforsleep_ok_btn: string 2429 | nightscreentimemgmt_sleepreminders_modal_readyforsleep_delay_btn_variantone: string 2430 | screentime_breakreminder_modal_timetotakeabreak_title: string 2431 | screentime_breakreminder_modal_timetotakeabreak_desc_1: string 2432 | screentime_breakreminder_modal_editreminder_link: string 2433 | screentime_breakreminder_modal_ok_btn: string 2434 | screentime_breakreminder_modal_snooze_link: string 2435 | dailyscreentime_notifreminder_header_ready: string 2436 | familyPairing_dailyScreenTime_intervention_returnToTikTok_toast: string 2437 | dailyscreentime_notifreminder_button_returntotiktok: string 2438 | dailyscreentime_introsheet_minors_heading: string 2439 | dailyscreentime_introsheet_minors_firstbullet_logoff: string 2440 | dailyscreentime_introsheet_minors_secondbullet_settingsprivacy: string 2441 | dailyscreentime_introsheet_minors_firstbutton_gotit: string 2442 | dailyscreentime_introsheet_minors_secondbutton_manage: string 2443 | dailyscreentime_notifreminder_desc_hoursminutes: string 2444 | 'Got it': string 2445 | about_this_ad_fallback_description1: string 2446 | about_this_ad_fallback_more_info_hyperlink_2: string 2447 | about_this_ad_fallback_adjust_settings: string 2448 | accessibilityLabels_home_skipContentFeed: string 2449 | accessibilityLabels_forYou_nav_messages_btn: string 2450 | wbs_goto_bc_modal_feature3_title: string 2451 | wbs_goto_bc_modal_feature3_content: string 2452 | wbs_goto_bc_modal_feature1_title: string 2453 | wbs_goto_bc_modal_feature1_content: string 2454 | wbs_goto_bc_modal_title: string 2455 | wbs_goto_bc_modal_btn: string 2456 | pc_web_dark_mode_popup_header: string 2457 | pc_web_dark_mode_popup_body: string 2458 | desktop_app_downloadPopup_header: string 2459 | pcWeb_desktopApp_maintainPopup_body: string 2460 | desktop_app_downloadPopup_cta: string 2461 | desktop_app_upToDate_toast: string 2462 | desktop_app_tab_settings: string 2463 | desktop_app_tab_updateTikTok: string 2464 | dsa_illegal_more_options_link: string 2465 | report_inbox_video: string 2466 | report_inbox_comment: string 2467 | report_inbox_account: string 2468 | report_inbox_live: string 2469 | report_inbox_livecomment: string 2470 | report_inbox_directmessage: string 2471 | report_inbox_sound: string 2472 | report_inbox_hashtag: string 2473 | shoutouts_detail_comment_report_title: string 2474 | tns_intro_reporter_title: string 2475 | profile_page_events_list: string 2476 | qareport_question: string 2477 | report_inbox_title: string 2478 | inbox_default_text: string 2479 | Inbox_Comments_on_your_videos: string 2480 | Inbox_When_someone_comments_on__one_of_your_videos_you_ll_see_it_here: string 2481 | Inbox_New_followers: string 2482 | Inbox_When_someone_new_follows_you_you_ll_see_it_here: string 2483 | Inbox_Likes_on_your_videos: string 2484 | Inbox_When_someone_likes_one_of_your_videos_you_ll_see_it_here: string 2485 | Inbox_Mentions_of_You: string 2486 | Inbox_When_someone_mentions_you_you_ll_see_it_here: string 2487 | Inbox_replied_to_your_comment: string 2488 | Inbox_commented: string 2489 | inbox_videoreply: string 2490 | Inbox_created_a_duet_with_you: string 2491 | Inbox_is_following_you: string 2492 | Inbox_started_following_you: string 2493 | photomode_inbox_liked: string 2494 | Inbox_liked_your_video: string 2495 | Inbox_liked_your_comment: string 2496 | Inbox_and: string 2497 | Inbox_others: string 2498 | in_app_push_mention_in_photo: string 2499 | Inbox_mentioned_you_in_a_video: string 2500 | Inbox_mentioned_you_in_a_comment: string 2501 | system_notifications_inbox_header: string 2502 | inbox_request_accept: string 2503 | Inbox_Follow_requests: string 2504 | Inbox_Today: string 2505 | Inbox_Yesterday: string 2506 | Inbox_This_Week: string 2507 | Inbox_This_Month: string 2508 | Inbox_Previous: string 2509 | Inbox_All: string 2510 | Inbox_Likes: string 2511 | Inbox_Comments: string 2512 | Inbox_Mentions: string 2513 | Inbox_Notifications: string 2514 | system_notifications_details_button: string 2515 | accessibilityLabels_forYou_btn_inbox: string 2516 | Inbox: string 2517 | live_creator_hub_home_desc: string 2518 | editprofile_feedtooltip_title: string 2519 | editprofile_feedtooltip_subtitle: string 2520 | tiktok_series_webapp_tooltip_get_started: string 2521 | accessibilityLabels_forYou_nav_language_back_btn: string 2522 | desktop_kb_shortcuts_menu: string 2523 | accessibilityLabels_settings_darkModeOn: string 2524 | accessibilityLabels_settings_darkModeOff: string 2525 | 'View profile': string 2526 | tiktok_series_webapp_option: string 2527 | ls_live_studio: string 2528 | web_business_suite_entry: string 2529 | live_center_title: string 2530 | live_creator_hub_name: string 2531 | desktop_app_accountSettings: string 2532 | accessibilityLabels_settings_language: string 2533 | pc_web_dark_mode: string 2534 | login_fb_noLonger_LogInEase: string 2535 | Log_out_sheet_2: string 2536 | login_fb_confirmLogOut_body: string 2537 | login_fb_confirmLogOut_stay_cta: string 2538 | scheduler_welcome_tooltip_title: string 2539 | scheduler_welcome_tooltip_des: string 2540 | tenMinPlusUpload_webPage_introduceToolTip_title: string 2541 | tenMinPlusUpload_webPage_introduceToolTip_body: string 2542 | new_feature_guidance_Upload: string 2543 | podcasts_linkFullEpisodes_linkPodcastPage_tooltip: string 2544 | accessibilityLabels_forYou_nav_upload_btn: string 2545 | accessibilityLabels_forYou_nav_settings_btn: string 2546 | push_popup_title: string 2547 | push_popup_content: string 2548 | push_popup_btn1: string 2549 | push_popup_btn2: string 2550 | network_error_title: string 2551 | network_error_sub: string 2552 | settings_updated: string 2553 | Public: string 2554 | Settings_ads_page_adpersonalization_title: string 2555 | Adv_settings_warning_text: string 2556 | Adv_settings_warning_description: string 2557 | Adv_settings_page_help_text: string 2558 | Adv_settings_page_hide_adv_title: string 2559 | inbox_follow_failed_banned: string 2560 | inbox_follow_failed_noconnection: string 2561 | inbox_follow_failed_other: string 2562 | webapp_forYoufeed_videoRemoved_toast: string 2563 | GENERAL: string 2564 | Explore: string 2565 | TRENDING: string 2566 | search_Submission_Failed_tips: string 2567 | sug_report_relevant: string 2568 | view_all_results: string 2569 | accessibilityLabels_search_suggestions: string 2570 | embed_music_card_see_more: string 2571 | web_search_clear_btn: string 2572 | personalisedSearch_searchResults_searchBlankPage_manageSearchLabel: string 2573 | web_search_recent_header: string 2574 | search_feedback_success_tips1: string 2575 | Web_report_report_detail: string 2576 | avia_law_report_received_confirm: string 2577 | dailyscreentime_featurescreen_toast_editedtime: string 2578 | screenTime_screenTimeBreaks_manageTime_editBreak_toast: string 2579 | error_toast: string 2580 | screenTime_sleepReminders_setSleepTime_toast: string 2581 | nightscreentimemgmt_sleepreminders_toast_editsleeptime: string 2582 | family_safety_mode_locked_mode_indicator: string 2583 | screentimedash_digitalwellbeing_dailyscreentime_desc: string 2584 | Web_report_block_who: string 2585 | Web_report_block_detail: string 2586 | copyright_check_post_popup_cancel: string 2587 | km_report_question: string 2588 | km_pick_reason: string 2589 | choosepassword_button: string 2590 | Web_report_description_NetzDG: string 2591 | Signature: string 2592 | Sign_here: string 2593 | Report_confirmation: string 2594 | avia_law_false_report_warning: string 2595 | Web_report_description_tips: string 2596 | Web_report_you_can_also: string 2597 | dsa_illegal_report_trustedflaggerlink: string 2598 | dsa_illegal_report_trustedflagger: string 2599 | dsa_report_penalty_reminder: string 2600 | dsa_illegal_report_email: string 2601 | dsa_illegal_report_fill_email: string 2602 | dsa_illegal_report_trustedflagger_fill_email: string 2603 | dsa_illegal_detail_country: string 2604 | dsa_illegal_detail_law: string 2605 | dsa_illegal_cite_law_desc: string 2606 | dsa_illegal_detail_explanation: string 2607 | dsa_illegal_report_explanation_desc: string 2608 | dsa_illegal_appeal_signature: string 2609 | dsa_illegal_sign_legal_name: string 2610 | dsa_illegal_confirm_accuracy: string 2611 | dsa_illegal_report_trustedflagger_email: string 2612 | dsa_illegal_select_region: string 2613 | Web_report_account_impersonated_search: string 2614 | Web_report_account_impersonated: string 2615 | Web_report_account_impersonated_description: string 2616 | dsa_illegal_select_country_optional: string 2617 | dailyscreentime_featurescreen_desc_balanceyourday: string 2618 | dailyscreentime_featurescreen_firstbullet_settime: string 2619 | dailyscreentime_featurescreen_firstbullet_settime_desc_choose: string 2620 | dailyscreentime_featurescreen_secondbullet_getnotified: string 2621 | dailyscreentime_featurescreen_secondbullet_getnotified_desc_close: string 2622 | screenTime_web_dailyscreentime_mainSetting_toggle_desc: string 2623 | customizeSTM_screenTimeLimit_option_sameLimit: string 2624 | screenTime_web_setting_customTime_option: string 2625 | customizeSTM_screenTimeLimit_option_customLimit: string 2626 | screenTime_web_dailyscreentime_manageTime_modal_done_btn: string 2627 | nightscreentimemgmt_setsleeptime_halfsheet_am_desc: string 2628 | nightscreentimemgmt_setsleeptime_halfsheet_pm_desc: string 2629 | nightscreentimemgmt_sleepreminders_sleeptime_on_secondline_teens: string 2630 | nightscreentimemgmt_sleepreminders_sleeptime_on_secondline_adults: string 2631 | nightscreentimemgmt_sleepreminders_defaultscreen_desc: string 2632 | nightscreentimemgmt_sleepreminders_defaultscreen_setsleeptimebullet_title: string 2633 | nightscreentimemgmt_sleepreminders_defaultscreen_setsleeptimebullet_desc: string 2634 | nightscreentimemgmt_sleepreminders_defaultscreen_pushnotifsbullet_title: string 2635 | nightscreentimemgmt_sleepreminders_defaultscreen_pushnotifsbullet_teens_desc: string 2636 | nightscreentimemgmt_sleepreminders_defaultscreen_pushnotifsbullet_adults_desc: string 2637 | screenTime_web_sleepReminders_mainSetting_toggle_desc: string 2638 | screentime_settings_screentimebreaks_intro_desc: string 2639 | screentime_settings_screentimebreaks_intro_schedulebreaks_heading: string 2640 | screentime_settings_screentimebreaks_actionsheet_desc_returninguser: string 2641 | screentime_settings_screentimebreaks_intro_tailoryourexp_heading: string 2642 | screentime_settings_screentimebreaks_intro_tailoryourexp_desc: string 2643 | screenTime_web_screenTimeBreaks_mainSetting_toggle_desc: string 2644 | pcWeb_guestLogin_contToVideo: string 2645 | pcWeb_guestLogin_guest: string 2646 | unit_week: string 2647 | unit_day: string 2648 | unit_hr: string 2649 | unit_min: string 2650 | unit_sec: string 2651 | time_ago: string 2652 | syntheticMedia_feed_bottomBanner_AIGCLabel: string 2653 | AIGC_FYP_descSection_label: string 2654 | pcWeb_autoScroll_on: string 2655 | pcWeb_autoScroll_off: string 2656 | desktop_kb_shortcuts_tooltip_like_vid: string 2657 | desktop_kb_shortcuts_tooltip_mute_unmute_vid: string 2658 | desktop_kb_shortcuts_modal: string 2659 | desktop_kb_shortcuts_tooltip_title: string 2660 | link_close_popup: string 2661 | bc_disclosure_tag_ecommerce_us: string 2662 | bc_disclosure_tag_ecommerce_uk: string 2663 | bc_new_disclosure: string 2664 | tcm_closedLoop_commercialContent_brandOrganic_videoTag: string 2665 | scm_label_and_appeal_modal_title: string 2666 | scm_label_and_appeal_modal_desc: string 2667 | scm_label_and_appeal_modal_button_learn_more: string 2668 | scm_label_and_appeal_modal_button_dismiss: string 2669 | ttba_ob_switchouterr_title: string 2670 | ttba_ob_switchouterr_title_lttfb: string 2671 | ttba_ob_switchouterr_title_lmp: string 2672 | ttba_ob_switchouterr_title_seller: string 2673 | ttba_ob_switchouterr_subtext: string 2674 | ttba_ob_switchouterr_subtext_lttfb: string 2675 | ttba_ob_switchouterr_subtext_lmp: string 2676 | ttba_ob_switchouterr_subtext_seller: string 2677 | switched_to_personal: string 2678 | add_windows_store_badge_download_app_stores: string 2679 | add_windows_store_badge_get_tiktok_app: string 2680 | add_windows_store_badge_scan_qr: string 2681 | engagement: string 2682 | direct_meaasge_sending_ban_feedback_again: string 2683 | nonpersonalizedFeeds_LIVEfeed_label_mainString_personalizationOn: string 2684 | nonpersonalizedFeeds_LIVEfeed_label_mainString: string 2685 | nonpersonalizedFeeds_turnOff_modal_toggle_bodyFull: string 2686 | nonpersonalizedFeeds_turnOn_modal_toggle_bodyFull: string 2687 | personalisedSearch_searchResults_actionSheet_bodyPara1: string 2688 | personalisedSearch_searchResults_actionSheet_bodyPara1V2: string 2689 | nonpersonalizedFeeds_turnOn_modal_toggle_headline: string 2690 | personalisedSearch_searchResults_actionSheet_header: string 2691 | personalisedSearch_searchResults_actionSheet_bodyPara2Bold1: string 2692 | nonpersonalizedFeeds_settings_contentPreferences_entrypoint: string 2693 | personalisedSearch_searchResults_actionSheet_toggle: string 2694 | personalisedSearch_searchResults_actionSheet_btn: string 2695 | search_videosearchbar_recommended_generic_1: string 2696 | please_input_search_keyword: string 2697 | seo_serp_expansion_num1: string 2698 | seo_aggre_metadesc2: string 2699 | 'SERP discover title': string 2700 | 'TikTok i18n keywords': string 2701 | SEO_discover_title: string 2702 | SEO_discover_desc: string 2703 | SEO_following_title: string 2704 | SEO_following_desc: string 2705 | hashtag_SEO_title2: string 2706 | hashtag_SEO_desc1: string 2707 | err_tag: string 2708 | SEO_qa_title_1: string 2709 | SEO_qa_desc_1: string 2710 | SEO_search_title: string 2711 | SEO_search_desc: string 2712 | SEO_Recharge_title: string 2713 | SEO_Recharge_desc: string 2714 | SEO_live_title: string 2715 | SEO_live_discover_title: string 2716 | SEO_live_discover_desc: string 2717 | SEO_live_desc: string 2718 | SEO_live_desc2: string 2719 | playlist_sharing_metatitle: string 2720 | playlist_sharing_metadescription: string 2721 | SEO_foryou_animals_title: string 2722 | SEO_foryou_animals_desc: string 2723 | SEO_foryou_beauty_title: string 2724 | SEO_foryou_beauty_desc: string 2725 | SEO_foryou_comedy_title: string 2726 | SEO_foryou_comedy_desc: string 2727 | SEO_foryou_dance_title: string 2728 | SEO_foryou_dance_desc: string 2729 | SEO_foryou_food_title: string 2730 | SEO_foryou_food_desc: string 2731 | SEO_foryou_gaming_title: string 2732 | SEO_foryou_gaming_desc: string 2733 | SEO_foryou_sports_title: string 2734 | SEO_foryou_sports_desc: string 2735 | share_live_event_title: string 2736 | share_live_event_desc: string 2737 | playlist_share_title: string 2738 | playlist_share_desc: string 2739 | user_SEO_official_title1: string 2740 | user_SEO_title1: string 2741 | share_effect_title: string 2742 | share_sticker_desc: string 2743 | share_sticker_preset: string 2744 | shared_collection_other_apps_title: string 2745 | shared_collection_other_apps_description: string 2746 | pm_mt_ls_download_button: string 2747 | 'TikTok | Make Your Day': string 2748 | serp_following_title: string 2749 | serp_following_desc: string 2750 | pc_web_skip_forward_5_sec: string 2751 | pc_web_skip_backward_5_sec: string 2752 | requested: string 2753 | 'QR CODE Text': string 2754 | pc_reflow_download: string 2755 | Get: string 2756 | seo_aggre_metadesc1: string 2757 | 'TikTok Trends': string 2758 | 'TikTok Trending': string 2759 | 'Trending Videos': string 2760 | 'Trending Hashtags': string 2761 | SEO_trending_title: string 2762 | SEO_trending_desc: string 2763 | seo_serp_hashtag_title: string 2764 | seo_serp_hashtag_desc: string 2765 | seo_serp_hashtag_desc1: string 2766 | 'TikTok i18n keywords for home': string 2767 | seo_serp_expansion_title: string 2768 | seo_serp_music_title: string 2769 | seo_serp_music_desc3: string 2770 | seo_serp_music_desc: string 2771 | seo_serp_music_desc1: string 2772 | seo_serp_music_desc2: string 2773 | err_sound: string 2774 | err_sound_copy: string 2775 | basicPoi_task2_metaTdk_title: string 2776 | basicPoi_task2_metaTdk_desc: string 2777 | basicPoi_task2_metaTdk_keyword: string 2778 | basicPoi_metaTdk_title: string 2779 | basicPoi_metaTdk_regional_desc: string 2780 | basicPoi_metaTdk_store_desc: string 2781 | basicPoi_metaTdk_keyword: string 2782 | basicPoi_metaTdk_storeSite: string 2783 | poidetails_tiktokplaces: string 2784 | poidetails_location_name_placehldtwo: string 2785 | music_SEO_desc3: string 2786 | seo_serp_user2_title: string 2787 | seo_serp_user1_title: string 2788 | seo_serp_user_desc: string 2789 | seo_serp_user_desc1: string 2790 | seo_serp_user_desc2: string 2791 | seo_serp_user_desc3: string 2792 | err_user: string 2793 | err_user_private: string 2794 | seo_serp_videotxt_desc1: string 2795 | seo_serp_videotxt_desc2: string 2796 | seo_serp_videotxt_desc3: string 2797 | seo_serp_searchQuery_desc: string 2798 | seo_serp_musicName_desc: string 2799 | serp_videoText_searchQuery_title: string 2800 | serp_videoText_searchQuery_title2: string 2801 | seo_serp_videotxt_title: string 2802 | seo_serp_videotxt_title2: string 2803 | err_vid_geo: string 2804 | err_vid: string 2805 | subVideo_outApp_sharing_title: string 2806 | basicPoi_toDoList_region: string 2807 | basicPoi_toDoList: string 2808 | seo_popular_sightseeing: string 2809 | basicPoi_sightSeeing: string 2810 | basicPoi_outdoorActivities: string 2811 | basicPoi_nightLife: string 2812 | basicPoi_familyFriendly: string 2813 | basicPoi_bestRestaurant_region: string 2814 | basicPoi_foodNDrinks: string 2815 | seo_popular_restaurant: string 2816 | basicPoi_brunchRestaurants: string 2817 | basicPoi_fineDining: string 2818 | basicPoi_seaFood: string 2819 | basicPoi_veganRestaurants: string 2820 | basicPoi_hotels_region: string 2821 | basicPoi_hotels: string 2822 | seo_popular_hotel: string 2823 | basicPoi_downtownHotels: string 2824 | basicPoi_petFriendly: string 2825 | basicPoi_airbnbs: string 2826 | basicPoi_luxuryHotels: string 2827 | basicPoi_parks_region: string 2828 | basicPoi_parks: string 2829 | seo_popular_park: string 2830 | basicPoi_amusementParks: string 2831 | basicPoi_dogParks: string 2832 | basicPoi_skateParks: string 2833 | basicPoi_indoorParks: string 2834 | basicPoi_shopping_region: string 2835 | basicPoi_shopping: string 2836 | seo_popular_shoppingMall: string 2837 | basicPoi_shoppingMalls: string 2838 | basicPoi_downtownShopping: string 2839 | basicPoi_vintageShopping: string 2840 | basicPoi_giftShops: string 2841 | } 2842 | 2843 | export interface SeoAbtest { 2844 | canonical: string 2845 | pageId: string 2846 | vidList: any[] 2847 | parameters: Parameters3 2848 | } 2849 | 2850 | export interface Parameters3 {} 2851 | 2852 | export interface WebappBrowserRedirectContext { 2853 | originalUrl: string 2854 | browserRedirectUrl: string 2855 | } 2856 | 2857 | export interface WebappVideoDetail { 2858 | itemInfo: ItemInfo 2859 | shareMeta: ShareMeta 2860 | statusCode: number 2861 | statusMsg: string 2862 | } 2863 | 2864 | export interface ItemInfo { 2865 | itemStruct: ItemStruct 2866 | } 2867 | 2868 | export interface ItemStruct { 2869 | id: string 2870 | desc: string 2871 | createTime: string 2872 | scheduleTime: number 2873 | video: Video 2874 | author: Author 2875 | music: Music 2876 | challenges: Challenge[] 2877 | stats: Stats 2878 | statsV2: StatsV2 2879 | warnInfo: any[] 2880 | originalItem: boolean 2881 | officalItem: boolean 2882 | textExtra: TextExtra[] 2883 | secret: boolean 2884 | forFriend: boolean 2885 | digged: boolean 2886 | itemCommentStatus: number 2887 | takeDown: number 2888 | effectStickers: any[] 2889 | privateItem: boolean 2890 | stickersOnItem: any[] 2891 | shareEnabled: boolean 2892 | comments: any[] 2893 | duetDisplay: number 2894 | stitchDisplay: number 2895 | imagePost: ImagePost 2896 | locationCreated: string 2897 | suggestedWords: any[] 2898 | contents: Content[] 2899 | collected: boolean 2900 | channelTags: any[] 2901 | item_control: ItemControl 2902 | isContentClassified: boolean 2903 | IsAigc: boolean 2904 | AIGCDescription: string 2905 | } 2906 | 2907 | export interface Video { 2908 | id: string 2909 | height: number 2910 | width: number 2911 | duration: number 2912 | ratio: string 2913 | cover: string 2914 | originCover: string 2915 | dynamicCover: string 2916 | playAddr: string 2917 | downloadAddr: string 2918 | shareCover: string[] 2919 | reflowCover: string 2920 | bitrate: number 2921 | encodedType: string 2922 | format: string 2923 | videoQuality: string 2924 | encodeUserTag: string 2925 | codecType: string 2926 | definition: string 2927 | subtitleInfos: any[] 2928 | zoomCover: ZoomCover 2929 | volumeInfo: VolumeInfo 2930 | bitrateInfo: BitrateInfo[] 2931 | VQScore: string 2932 | } 2933 | 2934 | export interface ZoomCover { 2935 | '240': string 2936 | '480': string 2937 | '720': string 2938 | '960': string 2939 | } 2940 | 2941 | export interface VolumeInfo { 2942 | Loudness: number 2943 | Peak: number 2944 | } 2945 | 2946 | export interface BitrateInfo { 2947 | Bitrate: number 2948 | QualityType: number 2949 | GearName: string 2950 | PlayAddr: PlayAddr 2951 | CodecType: string 2952 | MVMAF: string 2953 | } 2954 | 2955 | export interface PlayAddr { 2956 | DataSize: string 2957 | Uri: string 2958 | UrlList: string[] 2959 | UrlKey: string 2960 | FileHash: string 2961 | FileCs: string 2962 | } 2963 | 2964 | export interface Author { 2965 | id: string 2966 | shortId: string 2967 | uniqueId: string 2968 | nickname: string 2969 | avatarLarger: string 2970 | avatarMedium: string 2971 | avatarThumb: string 2972 | signature: string 2973 | createTime: number 2974 | verified: boolean 2975 | secUid: string 2976 | ftc: boolean 2977 | relation: number 2978 | openFavorite: boolean 2979 | commentSetting: number 2980 | duetSetting: number 2981 | stitchSetting: number 2982 | privateAccount: boolean 2983 | secret: boolean 2984 | isADVirtual: boolean 2985 | roomId: string 2986 | uniqueIdModifyTime: number 2987 | ttSeller: boolean 2988 | downloadSetting: number 2989 | recommendReason: string 2990 | nowInvitationCardUrl: string 2991 | nickNameModifyTime: number 2992 | isEmbedBanned: boolean 2993 | canExpPlaylist: boolean 2994 | suggestAccountBind: boolean 2995 | } 2996 | 2997 | export interface Music { 2998 | id: string 2999 | title: string 3000 | playUrl: string 3001 | coverLarge: string 3002 | coverMedium: string 3003 | coverThumb: string 3004 | authorName: string 3005 | original: boolean 3006 | duration: number 3007 | album: string 3008 | scheduleSearchTime: number 3009 | collected: boolean 3010 | preciseDuration: PreciseDuration 3011 | } 3012 | 3013 | export interface PreciseDuration { 3014 | preciseDuration: number 3015 | preciseShootDuration: number 3016 | preciseAuditionDuration: number 3017 | preciseVideoDuration: number 3018 | } 3019 | 3020 | export interface Challenge { 3021 | id: string 3022 | title: string 3023 | desc: string 3024 | profileLarger: string 3025 | profileMedium: string 3026 | profileThumb: string 3027 | coverLarger: string 3028 | coverMedium: string 3029 | coverThumb: string 3030 | } 3031 | 3032 | export interface Stats { 3033 | diggCount: number 3034 | shareCount: number 3035 | commentCount: number 3036 | playCount: number 3037 | collectCount: string 3038 | } 3039 | 3040 | export interface StatsV2 { 3041 | diggCount: string 3042 | shareCount: string 3043 | commentCount: string 3044 | playCount: string 3045 | collectCount: string 3046 | repostCount: string 3047 | } 3048 | 3049 | export interface TextExtra { 3050 | awemeId: string 3051 | start: number 3052 | end: number 3053 | hashtagId?: string 3054 | hashtagName: string 3055 | type: number 3056 | subType: number 3057 | isCommerce: boolean 3058 | userId?: string 3059 | userUniqueId?: string 3060 | secUid?: string 3061 | } 3062 | 3063 | export interface ImagePost { 3064 | images: Image[] 3065 | cover: Cover 3066 | shareCover: ShareCover 3067 | title: string 3068 | } 3069 | 3070 | export interface Image { 3071 | imageURL: ImageUrl 3072 | imageWidth: number 3073 | imageHeight: number 3074 | } 3075 | 3076 | export interface ImageUrl { 3077 | urlList: string[] 3078 | } 3079 | 3080 | export interface Cover { 3081 | imageURL: ImageUrl2 3082 | imageWidth: number 3083 | imageHeight: number 3084 | } 3085 | 3086 | export interface ImageUrl2 { 3087 | urlList: string[] 3088 | } 3089 | 3090 | export interface ShareCover { 3091 | imageURL: ImageUrl3 3092 | imageWidth: number 3093 | imageHeight: number 3094 | } 3095 | 3096 | export interface ImageUrl3 { 3097 | urlList: string[] 3098 | } 3099 | 3100 | export interface Content { 3101 | desc: string 3102 | textExtra: TextExtra2[] 3103 | } 3104 | 3105 | export interface TextExtra2 { 3106 | awemeId: string 3107 | start: number 3108 | end: number 3109 | hashtagId?: string 3110 | hashtagName: string 3111 | type: number 3112 | subType: number 3113 | isCommerce: boolean 3114 | userId?: string 3115 | userUniqueId?: string 3116 | secUid?: string 3117 | } 3118 | 3119 | export interface ItemControl {} 3120 | 3121 | export interface ShareMeta { 3122 | title: string 3123 | desc: string 3124 | } 3125 | 3126 | export interface WebappAB { 3127 | b_c: string 3128 | } 3129 | -------------------------------------------------------------------------------- /src/util/cookieHelper.ts: -------------------------------------------------------------------------------- 1 | import { Cookie } from 'set-cookie-parser' 2 | 3 | export default class CookieHelper { 4 | cookies: Cookie[] 5 | 6 | constructor(initatior: Cookie[]) { 7 | this.cookies = initatior || [] 8 | } 9 | setCookies(cookies: Cookie[]) { 10 | Object.assign(this.cookies, cookies) 11 | } 12 | deleteCookies(cookies: Cookie[]) { 13 | for (const cookie of cookies) { 14 | const index = this.cookies.findIndex((c) => c.name === cookie.name) 15 | if (index !== -1) { 16 | this.cookies.splice(index, 1) 17 | } 18 | } 19 | } 20 | getUpdatingCookies() { 21 | return this.cookies 22 | } 23 | getCookies() { 24 | return Object.freeze({ ...this.cookies }) 25 | } 26 | getCookiesAsString() { 27 | return this.cookies 28 | .map((cookie) => { 29 | return `${cookie.name}=${cookie.value}` 30 | }) 31 | .join('; ') 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/util/format.ts: -------------------------------------------------------------------------------- 1 | export function formatNumber(value: string): string { 2 | if (value === '0') return '0' 3 | 4 | // parse num to int 5 | const num = parseInt(value) 6 | if (isNaN(num)) return value 7 | 8 | if (num < 1000) return num.toString() 9 | if (num < 10000) return (num / 1000).toFixed(1) + 'k' 10 | if (num < 1000000) return (num / 1000).toFixed(1) + 'k' 11 | if (num < 10000000) return (num / 1000000).toFixed(1) + 'M' 12 | if (num < 1000000000) return (num / 1000000).toFixed(1) + 'M' 13 | if (num < 10000000000) return (num / 1000000000).toFixed(1) + 'B' 14 | return (num / 1000000000).toFixed(0) + 'B' 15 | } 16 | 17 | export function formatTime(time: number): string { 18 | const timeElapsed = Date.now() - time * 1000 // time elapsed in milliseconds 19 | const minutes = Math.floor(timeElapsed / 60000) 20 | const hours = Math.floor(minutes / 60) 21 | const days = Math.floor(hours / 24) 22 | 23 | if (days > 0) { 24 | return `${days}d ${hours % 24}h` 25 | } else if (hours > 0) { 26 | return `${hours}h ${minutes % 60}m` 27 | } else { 28 | return `${minutes}m` 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/util/generateAlternate.tsx: -------------------------------------------------------------------------------- 1 | import { Context } from 'hono' 2 | 3 | export default function generateAlternate(c: Context): { 4 | version: string 5 | type: string 6 | author_name: string 7 | author_url: string 8 | provider_name: string 9 | provider_url: string 10 | title: string 11 | } { 12 | const { unique_id, nickname, description } = c.req.query() 13 | const showSponsor = Math.random() < 0.1 // 1 in 10 chance to show sponsor message, gotta break even somehow 14 | 15 | const decodedDescription = description 16 | ? decodeURIComponent( 17 | new TextDecoder('utf-8').decode( 18 | Uint8Array.from(atob(decodeURIComponent(description)), (c) => c.charCodeAt(0)) 19 | ) 20 | ) 21 | : '' 22 | 23 | // Some Discord embed values are limited to 256 characters, truncate if necessary 24 | // See more: https://www.pythondiscord.com/pages/guides/python-guides/discord-embed-limits/ 25 | const truncatedDescription = 26 | decodedDescription.length > 256 ? decodedDescription.substring(0, 253) + '...' : decodedDescription 27 | 28 | return { 29 | version: '1.0', 30 | type: 'link', 31 | author_name: `${decodeURIComponent(nickname)} (@${decodeURIComponent(unique_id)})`, 32 | author_url: `https://www.tiktok.com${unique_id ? '/@' + unique_id : ''}`, 33 | provider_name: 34 | truncatedDescription || 35 | (showSponsor ? 'Use fxTikTok often? Consider supporting us on GitHub!' : 'fxTikTok - Embed with s/i/n'), 36 | provider_url: showSponsor ? 'https://github.com/sponsors/okdargy' : 'https://github.com/okdargy/fxTikTok', 37 | title: `TikTok by @${unique_id}` 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/util/metaHelper.tsx: -------------------------------------------------------------------------------- 1 | import { Context } from 'hono' 2 | import { env } from 'hono/adapter' 3 | 4 | export default function MetaHelper( 5 | c: Context, 6 | tags: { 7 | name: string 8 | content: string | null 9 | }[], 10 | alternate?: { 11 | [key: string]: string | number 12 | } 13 | ): JSX.Element { 14 | const { OFFLOAD_URL } = env(c) as { OFFLOAD_URL: string } 15 | let alternateUrl = new URL(OFFLOAD_URL || 'https://offload.tnktok.com' + '/generate/alternate') 16 | 17 | if (alternate) { 18 | for (const key in alternate) { 19 | alternateUrl.searchParams.set(key, encodeURIComponent(alternate[key].toString())) 20 | } 21 | } 22 | 23 | return ( 24 | 25 | 26 | {tags.map((tag) => (tag.content ? : null))} 27 | {alternate ? : null} 28 | 29 | 30 | ) 31 | } 32 | -------------------------------------------------------------------------------- /src/util/responseHelper.ts: -------------------------------------------------------------------------------- 1 | export const returnHTMLResponse = (content: string, status?: number, noCache?: boolean): Response => { 2 | return new Response(content, { 3 | status: status || 200, 4 | headers: { 5 | 'Content-Type': 'text/html; charset=utf-8', 6 | 'Cache-Control': noCache ? 'no-store' : 'public, max-age=3600' 7 | } 8 | }) 9 | } 10 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "module": "ESNext", 5 | "moduleResolution": "node", 6 | "esModuleInterop": true, 7 | "strict": true, 8 | "lib": ["esnext"], 9 | "types": ["@cloudflare/workers-types", "@types/jest"], 10 | "jsx": "react-jsx", 11 | "jsxImportSource": "hono/jsx", 12 | "paths": { 13 | "@/*": ["./src/*"] 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /wrangler.toml: -------------------------------------------------------------------------------- 1 | name = "fxtiktok-rewrite" 2 | compatibility_date = "2023-01-01" 3 | main = "src/index.ts" 4 | node_compat = true 5 | 6 | vars = { WORKER_ENV = "production", OFF_LOAD = "https://offload.tnktok.com" } 7 | 8 | [env.staging] 9 | name = "fxtiktok-rewrite-dev" 10 | vars = { WORKER_ENV = "staging", OFF_LOAD = "https://fxtiktok-rewrite-dev.dargy.workers.dev" } 11 | 12 | [observability.logs] 13 | enabled = true 14 | 15 | [env.local] 16 | vars = { WORKER_ENV = "local", OFF_LOAD = "http://127.0.0.1:8787" } --------------------------------------------------------------------------------