Moved to JS, using JSDOM and added Docker
This commit is contained in:
20 files changed
+1274
-198
No files matched your search
@@ -0,0 +1 @@
|
||||
node_modules
|
||||
+2
-2
@@ -11,6 +11,6 @@ trim_trailing_whitespace = true
|
||||
charset = utf-8
|
||||
|
||||
# 4 space indentation
|
||||
[*.py]
|
||||
[*.js]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
indent_size = 2
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
/.venv
|
||||
/.vscode
|
||||
__pycache__
|
||||
/node_modules
|
||||
@@ -0,0 +1,9 @@
|
||||
FROM node:17
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
COPY package.json ./
|
||||
RUN yarn install
|
||||
COPY . .
|
||||
EXPOSE 8080
|
||||
CMD [ "node", "server.js" ]
|
||||
@@ -1,26 +1,21 @@
|
||||
# SignTok
|
||||
Sign your TikTok urls easily.
|
||||
This is a port of [tiktok-signature](https://github.com/carcabot/tiktok-signature) to Python using Selenium and Selenium Stealth
|
||||
|
||||
[](https://heroku.com/deploy)
|
||||
This is a port of [tiktok-signature](https://github.com/carcabot/tiktok-signature) using JSDOM
|
||||
|
||||
## Installation
|
||||
```
|
||||
pip install -r requirements.txt
|
||||
yarn install
|
||||
```
|
||||
You also need to have Chrome installed
|
||||
|
||||
## Usage
|
||||
For webserver:
|
||||
```
|
||||
python web.py
|
||||
node server.py
|
||||
```
|
||||
Then you can send a POST request to localhost:8080 with a raw/plain body containing the url
|
||||
|
||||
For cli usage:
|
||||
```
|
||||
python cli.py
|
||||
node index.js 'YOUR_URL_HERE'
|
||||
```
|
||||
|
||||
## TODO
|
||||
* Docker
|
||||
@@ -1,89 +0,0 @@
|
||||
from os import getenv
|
||||
from selenium import webdriver
|
||||
from selenium_stealth import stealth
|
||||
from selenium.webdriver.chrome.options import Options
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
from urllib import parse
|
||||
from TikTokSigner.Utils import Utils
|
||||
|
||||
class Signer:
|
||||
DEFAULT_URL = 'https://www.tiktok.com/@tiktok/?lang=en'
|
||||
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (Windows NT 10.0; Win64; x64) Chrome/90.0.4430.85 Safari/537.36'
|
||||
TIMEOUT = 30
|
||||
driver: webdriver.Chrome
|
||||
|
||||
signature = ''
|
||||
xttparams = ''
|
||||
|
||||
def __init__(self):
|
||||
print('Starting Browser')
|
||||
options = Options()
|
||||
path = getenv('GOOGLE_CHROME_SHIM', '')
|
||||
options._binary_location = path
|
||||
options.add_argument("--headless")
|
||||
options.add_argument("--disable-gpu")
|
||||
options.add_argument("--no-sandbox")
|
||||
options.add_argument("--remote-debugging-port=9222")
|
||||
options.add_experimental_option("excludeSwitches", ["enable-automation"])
|
||||
options.add_experimental_option('useAutomationExtension', False)
|
||||
options.add_argument('--disable-blink-features=AutomationControlled')
|
||||
self.driver = webdriver.Chrome(options=options)
|
||||
stealth(self.driver,
|
||||
user_agent=self.USER_AGENT,
|
||||
languages=["en-US", "en"],
|
||||
vendor="Google Inc.",
|
||||
platform="Win32",
|
||||
webgl_vendor="Intel Inc.",
|
||||
renderer="Intel Iris OpenGL Engine",
|
||||
fix_hairline=True
|
||||
)
|
||||
|
||||
self.driver.get(self.DEFAULT_URL)
|
||||
WebDriverWait(self.driver, self.TIMEOUT).until(EC.presence_of_element_located((By.ID, 'app')))
|
||||
|
||||
# Load scripts
|
||||
with open('./js/signature.js') as f:
|
||||
signature = f.read()
|
||||
|
||||
with open('./js/xttparams.js') as f:
|
||||
xttparams = f.read()
|
||||
|
||||
self.driver.execute_script(signature)
|
||||
self.driver.execute_script(xttparams)
|
||||
|
||||
def navigator(self)-> dict:
|
||||
info = self.driver.execute_script("""
|
||||
return {
|
||||
deviceScaleFactor: window.devicePixelRatio,
|
||||
user_agent: window.navigator.userAgent,
|
||||
browser_language: window.navigator.language,
|
||||
browser_platform: window.navigator.platform,
|
||||
browser_name: window.navigator.appCodeName,
|
||||
browser_version: window.navigator.appVersion,
|
||||
}
|
||||
""")
|
||||
return info
|
||||
|
||||
def sign(self, url: str)-> dict:
|
||||
fp = Utils.verify_fp()
|
||||
# Add verifyFp to url
|
||||
url += '&verifyFp=' + fp
|
||||
signature = self.driver.execute_script('return window.byted_acrawler.sign(arguments[0])', {
|
||||
url: url
|
||||
})
|
||||
signed_url = url + '&_signature=' + signature
|
||||
|
||||
# Get params of url as dict
|
||||
params = dict(parse.parse_qsl(parse.urlsplit(url).query))
|
||||
xttparams = self.driver.execute_script('return window.genXTTParams(arguments[0])', params)
|
||||
return {
|
||||
'signature': signature,
|
||||
'verify_fp': fp,
|
||||
'signed_url': signed_url,
|
||||
'x-tt-params': xttparams
|
||||
}
|
||||
|
||||
def cleanup(self):
|
||||
self.driver.close()
|
||||
@@ -1,9 +0,0 @@
|
||||
import time
|
||||
import random
|
||||
import string
|
||||
|
||||
class Utils:
|
||||
@staticmethod
|
||||
def verify_fp()-> str:
|
||||
# TODO, add proper verify fp method
|
||||
return 'verify_5b161567bda98b6a50c0414d99909d4b'
|
||||
Whitespace-only changes.
@@ -4,19 +4,13 @@
|
||||
"keywords": [
|
||||
"tiktok",
|
||||
"api",
|
||||
"python"
|
||||
"node"
|
||||
],
|
||||
"website": "https://github.com/pablouser1/SignTok",
|
||||
"repository": "https://github.com/pablouser1/SignTok",
|
||||
"buildpacks": [
|
||||
{
|
||||
"url": "https://github.com/heroku/heroku-buildpack-google-chrome"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/heroku/heroku-buildpack-chromedriver"
|
||||
},
|
||||
{
|
||||
"url": "heroku/python"
|
||||
"url": "heroku/nodejs"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
from TikTokSigner.Signer import Signer
|
||||
from sys import argv
|
||||
import json
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(argv) > 1:
|
||||
signer = Signer()
|
||||
data = signer.sign(argv[1])
|
||||
nav = signer.navigator()
|
||||
res = {
|
||||
'status': 'ok',
|
||||
'data': {
|
||||
**data,
|
||||
'navigator': nav
|
||||
}
|
||||
}
|
||||
print(json.dumps(res))
|
||||
signer.cleanup()
|
||||
else:
|
||||
print('You need to type a url!')
|
||||
@@ -0,0 +1,9 @@
|
||||
const Signer = require("./src/Signer")
|
||||
|
||||
if (process.argv.length > 2) {
|
||||
const signer = new Signer()
|
||||
const url = process.argv[2]
|
||||
|
||||
const data = signer.sign(url)
|
||||
console.log(data)
|
||||
}
|
||||
+1
-1
@@ -1 +1 @@
|
||||
Function(function (t) { return 'w={S(S,K){if(!a[S]){a[S]={};for(y=0;y<S;y)a[S][S.charAt(y)]=y}a[S][K]}K=String.fromCharCode,a={},y={x:(K){null==K?"":""==K?null:y.y(K,32,(a){S("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",K.charAt(a})},y:(S,a,y){p,m,o,T,l,r,k,i=[],J=4,q=4,j=3,I="",b=[],z={val:y(0),position:a,index:1};for(p=0;p<3;p+=1)i[p]=p;for(o=0,l=Math.pow(2,2),r=1;r!=l;)T=z.val&z.position,z.position>>=1,0==z.position&&(z.position=a,z.val=y(z.index,o|=(T>0?1:0)*r,r<<=1;switch(o){case 0:for(o=0,l=Math.pow(2,8),r=1;r!=l;)T=z.val&z.position,z.position>>=1,0==z.position&&(z.position=a,z.val=y(z.index,o|=(T>0?1:0)*r,r<<=1;k=K(o)1:for(o=0,l=Math.pow(2,16),r=1;r!=l;)T=z.val&z.position,z.position>>=1,0==z.position&&(z.position=a,z.val=y(z.index,o|=(T>0?1:0)*r,r<<=1;k=K(o)2:""}for(i[3]=k,m=k,b.push(k);;){if(z.index>S)"";for(o=0,l=Math.pow(2,j),r=1;r!=l;)T=z.val&z.position,z.position>>=1,0==z.position&&(z.position=a,z.val=y(z.index,o|=(T>0?1:0)*r,r<<=1;switch(k=o){case 0:for(o=0,l=Math.pow(2,8),r=1;r!=l;)T=z.val&z.position,z.position>>=1,0==z.position&&(z.position=a,z.val=y(z.index,o|=(T>0?1:0)*r,r<<=1;i[q]=K(o),k=q-1,J--1:for(o=0,l=Math.pow(2,16),r=1;r!=l;)T=z.val&z.position,z.position>>=1,0==z.position&&(z.position=a,z.val=y(z.index,o|=(T>0?1:0)*r,r<<=1;i[q]=K(o),k=q-1,J--2:b.join("")}if(0==J&&(J=Math.pow(2,j),j),i[k])I=i[k]if(k!==q)null;I=m+m.charAt(0)}b.push(I),i[q]=m+I.charAt(0),m=I,0==--J&&(J=Math.pow(2,j),j)}}};y};""==typeof define&&define.amd?define({w}):"undefined"!=typeof module&&null!=module?module.exports=w:"undefined"!=typeof angular&&null!=angular&&angular.module("w",[]).factory("w",{w}),eval(w.x("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 truncated
|
||||
Function(function (t) { return 'w={S(S,K){if(!a[S]){a[S]={};for(y=0;y<S;y)a[S][S.charAt(y)]=y}a[S][K]}K=String.fromCharCode,a={},y={x:(K){null==K?"":""==K?null:y.y(K,32,(a){S("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",K.charAt(a})},y:(S,a,y){p,m,o,T,l,r,k,i=[],J=4,q=4,j=3,I="",b=[],z={val:y(0),position:a,index:1};for(p=0;p<3;p+=1)i[p]=p;for(o=0,l=Math.pow(2,2),r=1;r!=l;)T=z.val&z.position,z.position>>=1,0==z.position&&(z.position=a,z.val=y(z.index,o|=(T>0?1:0)*r,r<<=1;switch(o){case 0:for(o=0,l=Math.pow(2,8),r=1;r!=l;)T=z.val&z.position,z.position>>=1,0==z.position&&(z.position=a,z.val=y(z.index,o|=(T>0?1:0)*r,r<<=1;k=K(o)1:for(o=0,l=Math.pow(2,16),r=1;r!=l;)T=z.val&z.position,z.position>>=1,0==z.position&&(z.position=a,z.val=y(z.index,o|=(T>0?1:0)*r,r<<=1;k=K(o)2:""}for(i[3]=k,m=k,b.push(k);;){if(z.index>S)"";for(o=0,l=Math.pow(2,j),r=1;r!=l;)T=z.val&z.position,z.position>>=1,0==z.position&&(z.position=a,z.val=y(z.index,o|=(T>0?1:0)*r,r<<=1;switch(k=o){case 0:for(o=0,l=Math.pow(2,8),r=1;r!=l;)T=z.val&z.position,z.position>>=1,0==z.position&&(z.position=a,z.val=y(z.index,o|=(T>0?1:0)*r,r<<=1;i[q]=K(o),k=q-1,J--1:for(o=0,l=Math.pow(2,16),r=1;r!=l;)T=z.val&z.position,z.position>>=1,0==z.position&&(z.position=a,z.val=y(z.index,o|=(T>0?1:0)*r,r<<=1;i[q]=K(o),k=q-1,J--2:b.join("")}if(0==J&&(J=Math.pow(2,j),j),i[k])I=i[k]if(k!==q)null;I=m+m.charAt(0)}b.push(I),i[q]=m+I.charAt(0),m=I,0==--J&&(J=Math.pow(2,j),j)}}};y};""==typeof define&&define.amd?define({w}):"undefined"!=typeof module&&null!=module?module.exports=w:"undefined"!=typeof angular&&null!=angular&&angular.module("w",[]).factory("w",{w}),eval(w.x("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 truncated
|
||||
@@ -1,2 +0,0 @@
|
||||
var CryptoJS=CryptoJS||function(e,t){var r={},n=r.lib={},i=n.Base=function(){function e(){}return{extend:function(t){e.prototype=this;var r=new e;return t&&r.mixIn(t),r.hasOwnProperty("init")&&this.init!==r.init||(r.init=function(){r.$super.init.apply(this,arguments)}),r.init.prototype=r,r.$super=this,r},create:function(){var e=this.extend();return e.init.apply(e,arguments),e},init:function(){},mixIn:function(e){for(var t in e)e.hasOwnProperty(t)&&(this[t]=e[t]);e.hasOwnProperty("toString")&&(this.toString=e.toString)},clone:function(){return this.init.prototype.extend(this)}}}(),c=n.WordArray=i.extend({init:function(e,t){e=this.words=e||[],this.sigBytes=null!=t?t:4*e.length},toString:function(e){return(e||f).stringify(this)},concat:function(e){var t=this.words,r=e.words,n=this.sigBytes,i=e.sigBytes;if(this.clamp(),n%4)for(var c=0;c<i;c++){var o=r[c>>>2]>>>24-c%4*8&255;t[n+c>>>2]|=o<<24-(n+c)%4*8}else if(r.length>65535)for(c=0;c<i;c+=4)t[n+c>>>2]=r[c>>>2];else t.push.apply(t,r);return this.sigBytes+=i,this},clamp:function(){var t=this.words,r=this.sigBytes;t[r>>>2]&=4294967295<<32-r%4*8,t.length=e.ceil(r/4)},clone:function(){var e=i.clone.call(this);return e.words=this.words.slice(0),e},random:function(t){for(var r,n=[],i=function(t){t=t;var r=987654321,n=4294967295;return function(){var i=((r=36969*(65535&r)+(r>>16)&n)<<16)+(t=18e3*(65535&t)+(t>>16)&n)&n;return i/=4294967296,(i+=.5)*(e.random()>.5?1:-1)}},o=0;o<t;o+=4){var f=i(4294967296*(r||e.random()));r=987654071*f(),n.push(4294967296*f()|0)}return new c.init(n,t)}}),o=r.enc={},f=o.Hex={stringify:function(e){for(var t=e.words,r=e.sigBytes,n=[],i=0;i<r;i++){var c=t[i>>>2]>>>24-i%4*8&255;n.push((c>>>4).toString(16)),n.push((15&c).toString(16))}return n.join("")},parse:function(e){for(var t=e.length,r=[],n=0;n<t;n+=2)r[n>>>3]|=parseInt(e.substr(n,2),16)<<24-n%8*4;return new c.init(r,t/2)}},a=o.Latin1={stringify:function(e){for(var t=e.words,r=e.sigBytes,n=[],i=0;i<r;i++){var c=t[i>>>2]>>>24-i%4*8&255;n.push(String.fromCharCode(c))}return n.join("")},parse:function(e){for(var t=e.length,r=[],n=0;n<t;n++)r[n>>>2]|=(255&e.charCodeAt(n))<<24-n%4*8;return new c.init(r,t)}},s=o.Utf8={stringify:function(e){try{return decodeURIComponent(escape(a.stringify(e)))}catch(e){throw new Error("Malformed UTF-8 data")}},parse:function(e){return a.parse(unescape(encodeURIComponent(e)))}},u=n.BufferedBlockAlgorithm=i.extend({reset:function(){this._data=new c.init,this._nDataBytes=0},_append:function(e){"string"==typeof e&&(e=s.parse(e)),this._data.concat(e),this._nDataBytes+=e.sigBytes},_process:function(t){var r=this._data,n=r.words,i=r.sigBytes,o=this.blockSize,f=i/(4*o),a=(f=t?e.ceil(f):e.max((0|f)-this._minBufferSize,0))*o,s=e.min(4*a,i);if(a){for(var u=0;u<a;u+=o)this._doProcessBlock(n,u);var d=n.splice(0,a);r.sigBytes-=s}return new c.init(d,s)},clone:function(){var e=i.clone.call(this);return e._data=this._data.clone(),e},_minBufferSize:0}),d=(n.Hasher=u.extend({cfg:i.extend(),init:function(e){this.cfg=this.cfg.extend(e),this.reset()},reset:function(){u.reset.call(this),this._doReset()},update:function(e){return this._append(e),this._process(),this},finalize:function(e){return e&&this._append(e),this._doFinalize()},blockSize:16,_createHelper:function(e){return function(t,r){return new e.init(r).finalize(t)}},_createHmacHelper:function(e){return function(t,r){return new d.HMAC.init(e,r).finalize(t)}}}),r.algo={});return r}(Math);!function(){var e=CryptoJS,t=e.lib.WordArray;e.enc.Base64={stringify:function(e){var t=e.words,r=e.sigBytes,n=this._map;e.clamp();for(var i=[],c=0;c<r;c+=3)for(var o=(t[c>>>2]>>>24-c%4*8&255)<<16|(t[c+1>>>2]>>>24-(c+1)%4*8&255)<<8|t[c+2>>>2]>>>24-(c+2)%4*8&255,f=0;f<4&&c+.75*f<r;f++)i.push(n.charAt(o>>>6*(3-f)&63));var a=n.charAt(64);if(a)for(;i.length%4;)i.push(a);return i.join("")},parse:function(e){var r=e.length,n=this._map,i=this._reverseMap;if(!i){i=this._reverseMap=[];for(var c=0;c<n.length;c++)i[n.charCodeAt(c)]=c}var o=n.charAt(64);if(o){var f=e.indexOf(o);-1!==f&&(r=f)}return function(e,r,n){for(var i=[],c=0,o=0;o<r;o++)if(o%4){var f=n[e.charCodeAt(o-1)]<<o%4*2,a=n[e.charCodeAt(o)]>>>6-o%4*2;i[c>>>2]|=(f|a)<<24-c%4*8,c++}return t.create(i,c)}(e,r,i)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}}(),CryptoJS.lib.Cipher||function(e){var t=CryptoJS,r=t.lib,n=r.Base,i=r.WordArray,c=r.BufferedBlockAlgorithm,o=t.enc,f=(o.Utf8,o.Base64),a=t.algo.EvpKDF,s=r.Cipher=c.extend({cfg:n.extend(),createEncryptor:function(e,t){return this.create(this._ENC_XFORM_MODE,e,t)},createDecryptor:function(e,t){return this.create(this._DEC_XFORM_MODE,e,t)},init:function(e,t,r){this.cfg=this.cfg.extend(r),this._xformMode=e,this._key=t,this.reset()},reset:function(){c.reset.call(this),this._doReset()},process:function(e){return this._append(e),this._process()},finalize:function(e){return e&&this._append(e),this._doFinalize()},keySize:4,ivSize:4,_ENC_XFORM_MODE:1,_DEC_XFORM_MODE:2,_createHelper:function(){function e(e){return"string"==tyLine truncated
|
||||
window.genXTTParams=function(e){return encryptParams(e)}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "signtok",
|
||||
"version": "1.0.0",
|
||||
"description": "Sign your TikTok requests easily",
|
||||
"repository": "https://github.com/pablouser1/SignTok",
|
||||
"author": "Pablo Ferreiro",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "node server.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"canvas": "^2.9.1",
|
||||
"crypto-js": "^4.1.1",
|
||||
"express": "^4.17.3",
|
||||
"jsdom": "^19.0.0"
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
async-generator==1.10
|
||||
attrs==21.4.0
|
||||
certifi==2021.10.8
|
||||
cffi==1.15.0
|
||||
cryptography==36.0.1
|
||||
h11==0.13.0
|
||||
idna==3.3
|
||||
outcome==1.1.0
|
||||
pycparser==2.21
|
||||
pyOpenSSL==22.0.0
|
||||
PySocks==1.7.1
|
||||
selenium==4.1.2
|
||||
selenium-stealth==1.0.6
|
||||
sniffio==1.2.0
|
||||
sortedcontainers==2.4.0
|
||||
trio==0.20.0
|
||||
trio-websocket==0.9.2
|
||||
urllib3==1.26.8
|
||||
wsproto==1.1.0
|
||||
@@ -0,0 +1,30 @@
|
||||
const Signer = require("./src/Signer")
|
||||
const bodyParser = require("body-parser")
|
||||
const express = require("express")
|
||||
|
||||
const port = process.env.PORT || 8080
|
||||
const app = express()
|
||||
app.use(bodyParser.text())
|
||||
|
||||
const signer = new Signer()
|
||||
|
||||
app.get('/', (req, res) => {
|
||||
res.redirect('https://github.com/pablouser1/SignTok')
|
||||
})
|
||||
|
||||
app.post("/signature", (req, res) => {
|
||||
const url = req.body
|
||||
const data = signer.sign(url)
|
||||
console.log("Sent data from request with url: " + url)
|
||||
res.send({
|
||||
status: "ok",
|
||||
data: {
|
||||
...data,
|
||||
navigator: signer.navigator()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`App listening on port ${port}`)
|
||||
})
|
||||
@@ -0,0 +1,78 @@
|
||||
const fs = require("fs")
|
||||
const Utils = require("./Utils")
|
||||
const { JSDOM, ResourceLoader } = require("jsdom")
|
||||
const CryptoJS = require("crypto-js")
|
||||
|
||||
class Signer {
|
||||
static DEFAULT_USERAGENT =
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36"
|
||||
static PASSWORD = CryptoJS.enc.Utf8.parse('webapp1.0+202106')
|
||||
/**
|
||||
* @type Window
|
||||
*/
|
||||
window = null
|
||||
|
||||
constructor(userAgent = Signer.DEFAULT_USERAGENT) {
|
||||
const signature_js = fs.readFileSync(__dirname + "/../js/signature.js", "utf-8")
|
||||
const resourceLoader = new ResourceLoader({
|
||||
userAgent
|
||||
})
|
||||
|
||||
const { window } = new JSDOM(``, {
|
||||
url: "https://www.tiktok.com",
|
||||
referrer: "https://www.tiktok.com",
|
||||
contentType: "text/html",
|
||||
includeNodeLocations: true,
|
||||
runScripts: "outside-only",
|
||||
resources: resourceLoader
|
||||
})
|
||||
this.window = window
|
||||
this.window.eval(signature_js.toString())
|
||||
this.window.byted_acrawler.init({
|
||||
"aid":24,
|
||||
"dfp":true
|
||||
})
|
||||
}
|
||||
|
||||
navigator() {
|
||||
return {
|
||||
deviceScaleFactor: this.window.devicePixelRatio,
|
||||
user_agent: this.window.navigator.userAgent,
|
||||
browser_language: this.window.navigator.language,
|
||||
browser_platform: this.window.navigator.platform,
|
||||
browser_name: this.window.navigator.appCodeName,
|
||||
browser_version: this.window.navigator.appVersion
|
||||
}
|
||||
}
|
||||
|
||||
signature(url) {
|
||||
return this.window.byted_acrawler.sign({ url })
|
||||
}
|
||||
|
||||
xttparams(params) {
|
||||
params += "&is_encryption=1"
|
||||
const crypt = CryptoJS.AES.encrypt(params, Signer.PASSWORD, {
|
||||
iv: Signer.PASSWORD,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
}).toString()
|
||||
return crypt
|
||||
}
|
||||
|
||||
sign(url) {
|
||||
const verifyFp = Utils.verify_fp()
|
||||
url += "&verifyFp=" + verifyFp
|
||||
const signature = this.signature(url)
|
||||
const signed_url = url + "&_signature=" + signature
|
||||
const params = new URL(url).searchParams.toString()
|
||||
const xttparams = this.xttparams(params)
|
||||
return {
|
||||
signature: signature,
|
||||
verify_fp: verifyFp,
|
||||
signed_url: signed_url,
|
||||
"x-tt-params": xttparams
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Signer
|
||||
@@ -0,0 +1,8 @@
|
||||
class Utils {
|
||||
static verify_fp() {
|
||||
// TODO, add proper verify fp method
|
||||
return "verify_68b8ccfa65726db8b3db0cc07821d696"
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Utils
|
||||
@@ -1,38 +0,0 @@
|
||||
import json
|
||||
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||
from TikTokSigner.Signer import Signer
|
||||
from os import getenv
|
||||
|
||||
signer = Signer()
|
||||
|
||||
class TikServer(BaseHTTPRequestHandler):
|
||||
def do_POST(self):
|
||||
if self.path == '/signature':
|
||||
content_length = int(self.headers['Content-Length'])
|
||||
post_data = self.rfile.read(content_length)
|
||||
url = post_data.decode()
|
||||
|
||||
data = signer.sign(url)
|
||||
nav = signer.navigator()
|
||||
|
||||
res = {
|
||||
'status': 'ok',
|
||||
'data': {
|
||||
**data,
|
||||
'navigator': nav
|
||||
}
|
||||
}
|
||||
|
||||
self.send_response(200)
|
||||
self.send_header('Content-type', 'application/json')
|
||||
self.end_headers()
|
||||
self.wfile.write(json.dumps(res).encode())
|
||||
|
||||
if __name__ == '__main__':
|
||||
PORT = getenv('PORT', 8080)
|
||||
try:
|
||||
print('Starting server')
|
||||
httpd = HTTPServer(('0.0.0.0', PORT), TikServer)
|
||||
httpd.serve_forever()
|
||||
except KeyboardInterrupt:
|
||||
httpd.shutdown()
|
||||
Reference in new issue
Block a user