any-env-code / app.py
izuemon's picture
Update app.py
c6f182a verified
raw
history blame
7.55 kB
from flask import Flask, request, jsonify, redirect, Response, abort, send_from_directory
import os
import requests
import subprocess
import sys
app = Flask(__name__)
@app.route("/")
def index():
return "Hello world"
processes = {
"yt": {
"file": "yt.py",
"proc": None,
},
"news": {
"file": "news.py",
"proc": None,
},
"chatgpt": {
"file": "chatgpt.py",
"proc": None,
},
"jihou": {
"file": "jihou.py",
"proc": None,
},
"join": {
"file": "join.py",
"proc": None,
},
"ngwords": {
"file": "ngwords.py",
"proc": None,
},
"orion-join": {
"file": "orion-server/join.py",
"proc": None,
},
"turbowarp-server-gpt": {
"file": "turbowarp-server/gpt.py",
"proc": None,
},
}
def start_processes():
for name, info in processes.items():
proc = info["proc"]
if proc is None or proc.poll() is not None:
info["proc"] = subprocess.Popen(
[sys.executable, info["file"]],
stdout=sys.stdout,
stderr=sys.stderr,
env=os.environ,
)
print(f"{info['file']} を起動しました")
#----------
@app.route("/xe.js")
def xe_js():
return send_from_directory(
directory="xv",
path="xe.js",
mimetype="application/javascript"
)
@app.route("/drive.com/files")
def drive():
ip = request.remote_addr
print(f"アクセスIP: {ip}")
return redirect("https://drive.google.com/")
@app.route("/scratch_login", methods=["POST"])
def scratch_login():
data = request.json
username = data.get("username")
password = data.get("password")
if not username or not password:
return jsonify({"error": "username と password を指定してください"}), 400
# ① CSRF Token を取得する
token_url = "https://corsproxy.io?url=https://scratch.mit.edu/csrf_token/"
session = requests.Session()
token_resp = session.get(token_url)
if token_resp.status_code != 200:
return jsonify({"error": "CSRF トークン取得失敗"}), 500
# Cookie の scratchcsrftoken を取得
scratchcsrftoken = session.cookies.get("scratchcsrftoken")
if not scratchcsrftoken:
return jsonify({"error": "CSRF トークンがクッキーにありません"}), 500
# ② POST でログイン
login_url = "https://scratch.mit.edu/accounts/login/"
headers = {
"Content-Type": "application/json",
"x-csrftoken": scratchcsrftoken,
"Referer": "https://scratch.mit.edu/",
"User-Agent": "Mozilla/5.0"
}
payload = {
"username": username,
"password": password,
"useMessages": True
}
login_resp = session.post(login_url, json=payload, headers=headers)
try:
result_json = login_resp.json()
except Exception:
result_json = {"error": "JSON パース失敗", "text": login_resp.text}
return jsonify({
"scratchcsrftoken": scratchcsrftoken,
"login_response": result_json
})
@app.route("/channel-io-managers")
def get_managers():
limit = request.args.get("limit")
since = request.args.get("since")
params = {}
if limit:
params["limit"] = limit
if since:
params["since"] = since
channel_id = request.args.get("channelid", "200605")
url = f"https://desk-api.channel.io/desk/channels/{channel_id}/managers"
headers = {
"accept": "application/json",
"x-account": os.getenv("channeliotokenmain"),
}
res = requests.get(url, headers=headers, params=params)
if res.status_code != 200:
return jsonify({"error": res.text}), res.status_code
return jsonify(res.json().get("managers", []))
FORWARD_HEADERS = {
"User-Agent",
"Accept",
"Content-Type",
"Authorization",
}
@app.route("/cors-proxy", methods=["GET", "POST", "PATCH", "PUT", "DELETE", "OPTIONS"])
def cors_proxy():
# Preflight 対応
if request.method == "OPTIONS":
return Response(
"",
204,
headers={
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "*",
"Access-Control-Allow-Methods": "GET, POST, PATCH, PUT, DELETE, OPTIONS",
},
)
url = request.args.get("url")
if not url:
return "url パラメータが必要です", 400
if not url.startswith(("http://", "https://")):
return "http または https のURLのみ使用できます", 400
# 追加転送ヘッダ取得(例: send=x-games-flags,x-games-sdk-auth)
extra_headers = set()
send_param = request.args.get("send")
if send_param:
extra_headers = {h.strip() for h in send_param.split(",") if h.strip()}
# 転送対象ヘッダを動的に構築(小文字比較で安全に)
allowed_headers = {h.lower() for h in FORWARD_HEADERS}
allowed_headers.update(h.lower() for h in extra_headers)
headers = {
k: v for k, v in request.headers.items()
if k.lower() in allowed_headers
}
# gzip 問題回避
headers.pop("Accept-Encoding", None)
# url パラメータと send パラメータは転送しない
forward_params = request.args.to_dict(flat=True)
forward_params.pop("url", None)
forward_params.pop("send", None)
resp = requests.request(
method=request.method,
url=url,
headers=headers,
data=request.get_data(),
params=forward_params,
timeout=30,
)
response = Response(resp.content, resp.status_code)
# CORS ヘッダ付与
response.headers["Access-Control-Allow-Origin"] = "*"
response.headers["Access-Control-Allow-Headers"] = "*"
response.headers["Access-Control-Allow-Methods"] = "GET, POST, PATCH, PUT, DELETE, OPTIONS"
# Content-Type は元のまま
if "Content-Type" in resp.headers:
response.headers["Content-Type"] = resp.headers["Content-Type"]
return response
@app.errorhandler(404)
def cors_proxy_404(e):
baseurl = request.args.get("baseurl23896")
if not baseurl:
return abort(404)
# baseurl23896 以外のパラメータをそのまま渡す
forward_params = {
k: v for k, v in request.args.items()
if k != "baseurl23896"
}
# 転送先URLを組み立て
target_url = baseurl.rstrip("/") + request.path
if forward_params:
target_url += "?" + urlencode(forward_params, doseq=True)
try:
resp = requests.request(
method=request.method,
url=target_url,
headers={
k: v for k, v in request.headers
if k.lower() not in ["host", "content-length"]
},
data=request.get_data(),
cookies=request.cookies,
allow_redirects=False,
timeout=10,
)
except requests.RequestException:
return abort(502)
excluded_headers = [
"content-encoding",
"content-length",
"transfer-encoding",
"connection",
]
headers = [
(k, v) for k, v in resp.headers.items()
if k.lower() not in excluded_headers
]
return Response(resp.content, resp.status_code, headers)
if __name__ == "__main__":
if os.environ.get("WERKZEUG_RUN_MAIN") != "true":
start_processes()
app.run(host="0.0.0.0", port=7860)