upload code
This commit is contained in:
parent
a0e59b59c0
commit
d3e621ce66
|
@ -0,0 +1,2 @@
|
||||||
|
*.pyc
|
||||||
|
cookies.txt
|
17
README.md
17
README.md
|
@ -1,3 +1,18 @@
|
||||||
# huggingface-proxy
|
# huggingface-proxy
|
||||||
|
|
||||||
Host a proxy server on Huggingface Spaces
|
_Host a proxy server on Huggingface Spaces._
|
||||||
|
|
||||||
|
### Setup
|
||||||
|
#### Space
|
||||||
|
1. Create a new Space using `./space/Dockerfile`.
|
||||||
|
2. Upload your rathole client config to the space under the path `./rathole-client.toml`
|
||||||
|
3. Upload `./space/server.py` and `./space/supervisord.conf`
|
||||||
|
4. "Factory Reboot" the space to get it to rebuild.
|
||||||
|
|
||||||
|
|
||||||
|
#### Keep Alive
|
||||||
|
On a local machine, run the keep alive script to prevent Huggingface from stopping your space due to "inactivity". You'll have to create a write API key on your account and save your cookies to `cookies.txt`.
|
||||||
|
|
||||||
|
```
|
||||||
|
python3 ./keepalive/keepalive.py --token hf_XXX --username XXX --cookies ./cookies.txt --headless
|
||||||
|
```
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Huggingface Proxy Upkeep Daemon
|
||||||
|
After=network.target
|
||||||
|
StartLimitIntervalSec=0
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
User=server
|
||||||
|
Group=server
|
||||||
|
Type=simple
|
||||||
|
ExecStart=/srv/server/huggingface-proxy/venv/bin/python3 /srv/server/huggingface-proxy/keepalive.py --token hf_XXX --username example --cookies /srv/server/huggingface-proxy/cookies.txt --headless
|
||||||
|
Restart=always
|
||||||
|
RestartSec=3
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
|
@ -0,0 +1,81 @@
|
||||||
|
import argparse
|
||||||
|
import random
|
||||||
|
import time
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from huggingface_hub import HfApi
|
||||||
|
from selenium.webdriver.common.by import By
|
||||||
|
from selenium.webdriver.support import expected_conditions as EC
|
||||||
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
|
|
||||||
|
from lib.hf import list_spaces, login
|
||||||
|
from lib.webdriver import create_driver, load_cookies, save_cookies
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("--cookies", required=True, help="Path to the file containing your HF cookies")
|
||||||
|
parser.add_argument("--token", required=True, help="Your HF API token")
|
||||||
|
parser.add_argument("--username", required=True, help="Your HF username")
|
||||||
|
parser.add_argument("--password", required=True, help="Your HF password")
|
||||||
|
parser.add_argument("--headless", action='store_true', help="Run Selinium in headless mode")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
cookies_file = Path(args.cookies).resolve().expanduser().absolute()
|
||||||
|
|
||||||
|
login(args.token)
|
||||||
|
|
||||||
|
driver = create_driver(args.headless)
|
||||||
|
|
||||||
|
driver.get(f'https://huggingface.co')
|
||||||
|
if cookies_file.exists():
|
||||||
|
load_cookies(cookies_file)
|
||||||
|
|
||||||
|
driver.get('https://huggingface.co/settings/profile')
|
||||||
|
if driver.current_url != 'https://huggingface.co/settings/profile':
|
||||||
|
print('Not logged in!')
|
||||||
|
username = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.NAME, "username")))
|
||||||
|
username.send_keys(args.username)
|
||||||
|
password = driver.find_element(By.NAME, "password")
|
||||||
|
password.send_keys(args.password)
|
||||||
|
login_button = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, '//button[@type="submit"]')))
|
||||||
|
login_button.click()
|
||||||
|
save_cookies(driver, cookies_file)
|
||||||
|
print('Manually logged in.')
|
||||||
|
else:
|
||||||
|
print('Auth is correct')
|
||||||
|
|
||||||
|
while True:
|
||||||
|
our_spaces = [x.id for x in list_spaces(args.username) if 'proxy' in x.id]
|
||||||
|
random.shuffle(our_spaces)
|
||||||
|
|
||||||
|
driver.get(f'https://huggingface.co')
|
||||||
|
time.sleep(5)
|
||||||
|
for space in our_spaces:
|
||||||
|
print(space)
|
||||||
|
driver.get(f'https://huggingface.co/spaces/{space}')
|
||||||
|
time.sleep(100)
|
||||||
|
|
||||||
|
# try:
|
||||||
|
if len(driver.find_elements(By.ID, 'captcha-container')):
|
||||||
|
print('CAPTCHA!!!')
|
||||||
|
else:
|
||||||
|
for iframe in driver.find_elements(By.TAG_NAME, 'iframe'):
|
||||||
|
src = iframe.get_attribute('src')
|
||||||
|
if 'hf.space' in src and '?__sign' in src:
|
||||||
|
print('Space is online')
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
api = HfApi()
|
||||||
|
try:
|
||||||
|
api.restart_space(repo_id=space)
|
||||||
|
print('Restarted space')
|
||||||
|
except Exception as e:
|
||||||
|
print('Failed to restart space!', e)
|
||||||
|
|
||||||
|
time.sleep(30)
|
||||||
|
|
||||||
|
# Avoid the captcha
|
||||||
|
driver.get('https://huggingface.co')
|
||||||
|
time.sleep(30)
|
||||||
|
sleep_time = 300
|
||||||
|
print(f'Sleeping {sleep_time} seconds...')
|
||||||
|
time.sleep(sleep_time)
|
|
@ -0,0 +1,14 @@
|
||||||
|
from huggingface_hub import login as hf_login
|
||||||
|
from huggingface_hub import HfApi
|
||||||
|
|
||||||
|
|
||||||
|
def login(token: str):
|
||||||
|
return hf_login(token)
|
||||||
|
|
||||||
|
|
||||||
|
def list_spaces(author: str):
|
||||||
|
api = HfApi()
|
||||||
|
result = []
|
||||||
|
for space in api.list_spaces(author=author):
|
||||||
|
result.append(space)
|
||||||
|
return result
|
|
@ -0,0 +1,46 @@
|
||||||
|
import http.cookiejar
|
||||||
|
|
||||||
|
import undetected_chromedriver as uc
|
||||||
|
from selenium.common import InvalidSessionIdException
|
||||||
|
from selenium.webdriver.chrome.options import Options
|
||||||
|
from selenium.webdriver.chrome.webdriver import WebDriver
|
||||||
|
from webdriver_manager.chrome import ChromeDriverManager
|
||||||
|
|
||||||
|
driver: WebDriver = None
|
||||||
|
|
||||||
|
|
||||||
|
def create_driver(headless=False):
|
||||||
|
global driver
|
||||||
|
if driver:
|
||||||
|
try:
|
||||||
|
driver.close()
|
||||||
|
except InvalidSessionIdException:
|
||||||
|
pass
|
||||||
|
|
||||||
|
options = Options()
|
||||||
|
if headless:
|
||||||
|
options.add_argument('--headless')
|
||||||
|
options.add_argument("--window-size=1920,1200")
|
||||||
|
options.add_argument("--incognito")
|
||||||
|
driver = uc.Chrome(driver_executable_path=ChromeDriverManager().install(), options=options, use_subprocess=False)
|
||||||
|
return driver
|
||||||
|
|
||||||
|
|
||||||
|
def load_cookies(file):
|
||||||
|
cookie_jar = http.cookiejar.MozillaCookieJar()
|
||||||
|
cookie_jar.load(file, ignore_discard=True, ignore_expires=True)
|
||||||
|
for cookie in cookie_jar:
|
||||||
|
driver.add_cookie({"name": cookie.name, "value": cookie.value, 'domain': cookie.domain})
|
||||||
|
|
||||||
|
|
||||||
|
def save_cookies(driver, location):
|
||||||
|
with open(location, 'w') as file:
|
||||||
|
file.write('# Netscape HTTP Cookie File\n')
|
||||||
|
for cookie in driver.get_cookies():
|
||||||
|
file.write(f"{cookie['domain']}\t"
|
||||||
|
f"{'TRUE' if cookie['domain'].startswith('.') else 'FALSE'}\t"
|
||||||
|
f"{cookie['path']}\t"
|
||||||
|
f"{'TRUE' if 'secure' in cookie else 'FALSE'}\t"
|
||||||
|
f"{str(int(cookie['expiry'])) if 'expiry' in cookie else '0'}\t"
|
||||||
|
f"{cookie['name']}\t"
|
||||||
|
f"{cookie['value']}\n")
|
|
@ -0,0 +1,5 @@
|
||||||
|
undetected-chromedriver
|
||||||
|
selenium==4.9.1
|
||||||
|
huggingface_hub
|
||||||
|
webdriver_manager
|
||||||
|
pyvirtualdisplay
|
|
@ -0,0 +1,24 @@
|
||||||
|
import argparse
|
||||||
|
import random
|
||||||
|
|
||||||
|
from huggingface_hub import HfApi
|
||||||
|
|
||||||
|
from lib.hf import list_spaces, login
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("--token", required=True, help="Your HF API token")
|
||||||
|
parser.add_argument("--username", required=True, help="Your HF username")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
login(args.token)
|
||||||
|
|
||||||
|
our_spaces = [x.id for x in list_spaces(args.username) if 'proxy' in x.id]
|
||||||
|
random.shuffle(our_spaces)
|
||||||
|
|
||||||
|
for space in our_spaces:
|
||||||
|
api = HfApi()
|
||||||
|
try:
|
||||||
|
api.restart_space(repo_id=space)
|
||||||
|
print(space)
|
||||||
|
except Exception as e:
|
||||||
|
print('Failed to restart space!', e)
|
|
@ -0,0 +1,25 @@
|
||||||
|
FROM debian:stable
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y git wget python3 python3-pip unzip && \
|
||||||
|
rm -rf /var/cache/apt/archives /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN mkdir -p /var/log/app
|
||||||
|
|
||||||
|
RUN git clone "https://git.evulid.cc/cyberes/huggingface-proxy.git" /app/huggingface
|
||||||
|
|
||||||
|
COPY ./rathole-client.toml /app/huggingface/rathole-client.toml
|
||||||
|
COPY ./server.py /app/huggingface/space/server.py
|
||||||
|
|
||||||
|
RUN wget https://github.com/rapiz1/rathole/releases/download/v0.5.0/rathole-x86_64-unknown-linux-gnu.zip -O /tmp/rathole.zip
|
||||||
|
RUN unzip /tmp/rathole.zip -d /app
|
||||||
|
|
||||||
|
RUN pip install --break-system-packages supervisor requests flask proxy.py "httpx[http2]"
|
||||||
|
|
||||||
|
RUN adduser --disabled-password --gecos '' --uid 1000 newuser
|
||||||
|
|
||||||
|
RUN chown -R newuser:newuser /app
|
||||||
|
|
||||||
|
EXPOSE 7860
|
||||||
|
USER newuser
|
||||||
|
|
||||||
|
CMD cd /app && /usr/local/bin/supervisord -c /app/huggingface/space/supervisord.conf
|
|
@ -0,0 +1,14 @@
|
||||||
|
import requests
|
||||||
|
from flask import Flask, Response
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/')
|
||||||
|
def home():
|
||||||
|
r = requests.get('https://api.ipify.org')
|
||||||
|
return Response(r.text, mimetype='text/plain')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(host="0.0.0.0", port=7860)
|
|
@ -0,0 +1,30 @@
|
||||||
|
[supervisord]
|
||||||
|
nodaemon=true
|
||||||
|
|
||||||
|
[program:rathole]
|
||||||
|
command=/bin/bash -c '/app/rathole -c /app/huggingface/rathole-client.toml 2>&1 | tee -a /app/rathole.log'
|
||||||
|
autostart=true
|
||||||
|
autorestart=true
|
||||||
|
stdout_logfile=/dev/fd/1
|
||||||
|
stdout_logfile_maxbytes=0
|
||||||
|
stderr_logfile=/dev/fd/2
|
||||||
|
stderr_logfile_maxbytes=0
|
||||||
|
|
||||||
|
[program:flask]
|
||||||
|
command=/usr/bin/python3 /app/huggingface/space/server.py
|
||||||
|
autostart=true
|
||||||
|
autorestart=true
|
||||||
|
stdout_logfile=/dev/fd/1
|
||||||
|
stdout_logfile_maxbytes=0
|
||||||
|
stderr_logfile=/dev/fd/2
|
||||||
|
stderr_logfile_maxbytes=0
|
||||||
|
|
||||||
|
[program:proxy]
|
||||||
|
command=proxy --hostname 0.0.0.0 --port 3128 --timeout 300 --plugins proxy.plugin.CloudflareDnsResolverPlugin
|
||||||
|
autostart=true
|
||||||
|
autorestart=true
|
||||||
|
stdout_logfile=/dev/fd/1
|
||||||
|
stdout_logfile_maxbytes=0
|
||||||
|
stderr_logfile=/dev/fd/2
|
||||||
|
stderr_logfile_maxbytes=0
|
||||||
|
environment=PORT=3128
|
Reference in New Issue