Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
pablouser1 committed Mar 6, 2022
0 parents commit 8465543
Show file tree
Hide file tree
Showing 14 changed files with 256 additions and 0 deletions.
16 changes: 16 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# EditorConfig is awesome: http://EditorConfig.org

# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
charset = utf-8

# 4 space indentation
[*.py]
indent_style = space
indent_size = 4
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/.venv
/.vscode
__pycache__
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2022 Pablo Ferreiro

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
1 change: 1 addition & 0 deletions Procfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
web: python web.py
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# 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

[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy)

## Installation
```
pip install -r requirements.txt
```
You also need to have Chrome installed

## Usage
For webserver:
```
python web.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
```

## TODO
* Docker
83 changes: 83 additions & 0 deletions TikTokSigner/Signer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
from os import getenv
from time import sleep
from selenium import webdriver
from selenium_stealth import stealth
from selenium.webdriver.chrome.options import Options
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'
driver: webdriver.Chrome

signature = ''
xttparams = ''

def __init__(self):
options = Options()
path = getenv('GOOGLE_CHROME_BIN', '')
options._binary_location = path
options.add_argument("start-maximized")
options.add_argument("--headless")
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)
sleep(2)

# 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()
9 changes: 9 additions & 0 deletions TikTokSigner/Utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import time
import random
import string

class Utils:
@staticmethod
def verify_fp()-> str:
# TODO, add proper verify fp method
return 'verify_5b161567bda98b6a50c0414d99909d4b'
Empty file added TikTokSigner/__init__.py
Empty file.
22 changes: 22 additions & 0 deletions app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "SignTok",
"description": "Sign TikTok requests",
"keywords": [
"tiktok",
"api",
"python"
],
"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"
}
]
}
18 changes: 18 additions & 0 deletions cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
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!')
1 change: 1 addition & 0 deletions js/signature.js

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions js/xttparams.js

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
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
35 changes: 35 additions & 0 deletions web.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
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):
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()

0 comments on commit 8465543

Please sign in to comment.