lanzouApi / index.py
lsfstar's picture
Upload 10 files
1e08a04 verified
import os
import re
import sys
from enum import Enum
from random import randint
from time import time
from urllib.parse import parse_qs, quote_plus, unquote, urlencode, urlparse
import requests
from cacheout import Cache
from flask import Flask, abort, jsonify, make_response, redirect, request
cache = Cache(maxsize=1024)
app = Flask(__name__)
ORIGIN = 'https://lanzoux.com'
RAND_IP = ''
class Client(Enum):
PC = 0
MOBILE = 1
def change_ip():
global RAND_IP
RAND_IP = '.'.join(str(randint(1, 254)) for _ in range(4))
def gen_headers(client: Client):
return {
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
'Referer': ORIGIN,
'User-Agent': [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36',
'Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Mobile Safari/537.36'
][client.value],
'X-Forwarded-For': RAND_IP
}
def get(url, client: Client):
return requests.get(url, headers=gen_headers(client), allow_redirects=False)
def post_data(url, data, client: Client):
return requests.post(url, data, headers={
**gen_headers(client),
'Content-Type': 'application/x-www-form-urlencoded'
})
def find_all(pattern, text):
return re.finditer(pattern, text, re.DOTALL | re.MULTILINE)
def find_first(pattern, text):
match = re.findall(pattern, text, re.DOTALL | re.MULTILINE)
if match:
return match[0]
def _oO0OO0O(OO0O0O0O):
import re as _0x1
def _0x2(_0x3):
def _0x4(_0x5):
_0x10 = ''
for _0x6 in _0x5: _0x10 += chr(_0x6)
return _0x10
_0x11 = [40, 39, 40, 63, 58, 92, 92, 46, 124, 91, 94, 39, 92, 92, 93, 41, 42, 39, 124, 34, 40, 63, 58, 92, 92, 46, 124, 91, 94, 34, 92, 92, 93, 41, 42, 34, 41]
_0x7 = _0x4(_0x11)
_0x8 = []
_0x12 = 0
def _0x9(_0xa):
nonlocal _0x12
_0x8.append(_0xa.group(0))
_0x13 = f"__{RAND_IP}_%d__" % _0x12
_0x12 += 1
return _0x13
_0xb = _0x1.sub(_0x7, _0x9, _0x3, flags=_0x1.VERBOSE | _0x1.DOTALL)
_0x14 = [47, 47, 46, 42, 63, 36, 124, 47, 92, 42, 46, 42, 63, 92, 42, 47]
_0xc = _0x4(_0x14)
_0xd = _0x1.sub(_0xc, '', _0xb, flags=_0x1.MULTILINE | _0x1.DOTALL)
_0x15 = 0
while _0x15 < len(_0x8):
_0xf = _0x8[_0x15]
_0xd = _0xd.replace(f"__{RAND_IP}_%d__" % _0x15, _0xf)
_0x15 += 1
return _0xd
return _0x2(OO0O0O0O)
def get_url(fid: str, client: Client, pwd=None):
def get_fake_url(text, params):
m_url = find_first(r"^\s*?[^/]+?{.*?url\s*?:\s*['\"](.*?php.*?)'", text)
result = post_data(f'{ORIGIN}/{m_url}', params, client).json()
return f"{result['dom']}/file/{result['url']}"
if client == Client.PC:
text = _oO0OO0O(get(f'{ORIGIN}/{fid}', client).text)
if pwd:
old_ver = find_first(r"^\s*?[^/]+?data *?: *?'([^']+?)'", text)
if old_ver:
params = old_ver + pwd
else:
for m in find_all(r"^\s*?[^/]+? ([^\d\s][\$\w]+? *?=.+?);", text):
try:
exec(m.group(1))
except Exception:
pass
for m in find_all(r"^\s*?[^/]+?data *?: *?({.+?})", text):
try:
data = eval(m.group(1))
if len(data.get('sign')) > 10:
break
except Exception:
pass
params = urlencode(data, quote_via=quote_plus)
else:
fn = find_first(r'iframe.+?src=\"([^\"]{20,}?)\"', text)
text = _oO0OO0O(get(f'{ORIGIN}/{fn}', client).text)
for m in find_all(r"^\s*?[^/]+? ([^\d\s][\$\w]+? *?=.+?);", text):
try:
exec(m.group(1))
except Exception:
pass
data = eval(find_first(r"^\s*?[^/]+?data *?: *?({.+?})", text))
params = urlencode(data, quote_via=quote_plus)
fake_url = get_fake_url(text, params)
else:
text = _oO0OO0O(get(f'{ORIGIN}/{fid}', client).text)
fid_with_params = find_first(r"[^/\n;]+? *?= *?['\"]/?tp/([^'\"]+?)['\"]", text)
text = _oO0OO0O(get(f'{ORIGIN}/tp/{fid_with_params}', client).text)
if pwd:
for m in find_all(r"^\s*?[^/]+? ([^\d\s][\$\w]+? *?=.+?);", text):
try:
exec(m.group(1))
except Exception:
pass
params = eval(find_first(r"^\s*?[^/]+? *?data *?: *?({.+?})", text))
fake_url = get_fake_url(text, params)
else:
url_pre = find_first(r"^\s*?[^/]+? *?= *?'(https?://[^']+?)'", text)
url_suf = find_first(r"^\s*?[^/]+?[$\w\s]+? *?= *?'(\?[^']+?)'", text)
fake_url = url_pre + url_suf
return get(fake_url, client).headers['location']
def fmt_size(num, suffix='B'):
for unit in ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z']:
if abs(num) < 1024.0:
return "%3.1f%s%s" % (num, unit, suffix)
num /= 1024.0
return "%.1f%s%s" % (num, 'Y', suffix)
def get_ttl(url):
e = parse_qs(urlparse(url).query).get('e', [time() + 600])[0]
return int(e) - int(time()) - 60
def get_full_info(cache_key, ttl, url):
info = cache.get(cache_key)
if info:
print(f'hit cache: {info}')
return info
headers = requests.head(url, allow_redirects=False).headers
info = {
'name': unquote(headers.get('Content-Disposition').split('filename=')[-1].strip()),
'size': fmt_size(int(headers.get('Content-Length'))),
'url': url,
}
cache.set(cache_key, info, ttl=ttl)
return info
def gen_json_response(code, msg, extra={}):
return make_response(jsonify({
'code': code,
'msg': msg,
**extra
}))
@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def catch_all(path):
url = request.args.get('url', '')
fid = url.split('/')[-1]
if not re.match(r"[\w]{4,}.*?", fid):
return gen_json_response(
-1,
'invalid link',
{
'examples': [
f'{request.base_url}?url={ORIGIN}/ifbCQ2u5gxxa&type=down',
f'{request.base_url}?url={ORIGIN}/i7tit9c&pwd=6svq&type=json',
]
}
)
pwd = request.args.get('pwd')
accept_type = request.args.get('type')
def respond(url, ttl=None):
if accept_type == 'down':
return redirect(url)
else:
return gen_json_response(
200,
'success',
{'data': get_full_info(f'{fid}/{pwd}/info', ttl, url)}
)
cache_key = f'{fid}/{pwd}/url'
url = cache.get(cache_key)
if url:
print(f'hit cache: {url}')
return respond(url)
change_ip()
errors = []
for client in Client:
try:
url = get_url(fid, client, pwd)
# https://rollbar.com/blog/throwing-exceptions-in-python/
# assert (url.startswith('1http')), f'Parse Error: fid: {fid}, client: {client}, pwd: {pwd}, url: {url}'
ttl = get_ttl(url)
cache.set(cache_key, url, ttl=ttl)
return respond(url, ttl)
except Exception as e:
errors.append(e)
pass
abort(500, errors)
@app.errorhandler(Exception)
def server_error(e):
return gen_json_response(
-2,
f'Link does not match pwd, or LanZouCloud has changed their webpage. Errors: {e}'
)
@app.after_request
def cors(response):
response.headers['Access-Control-Allow-Origin'] = '*'
return response
def test():
def request(fid, client: Client, pwd=None):
print(f'fid={fid}, client={client}, pwd={pwd}')
print(get_url(fid, client, pwd))
print('--------------------------------------')
for fid, pwd in {
'iDuSh22faxqj': '6q1d',
'ifbCQ2u5gxxa': None,
'i7tit9c': '6svq',
'i4wk2oh': None,
'iRujgdfrkza': None,
'dkbdv7': None,
}.items():
for c in Client:
request(fid, c, pwd)
if __name__ == '__main__':
port = int(os.getenv('PORT', '7860'))
# if len(sys.argv) <= 1 or sys.argv[1] != 'production':
# test()
app.run(host='0.0.0.0', port=port)