upload code

This commit is contained in:
Cyberes 2024-01-16 20:41:58 -07:00
parent a0e59b59c0
commit d3e621ce66
12 changed files with 272 additions and 1 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.pyc
cookies.txt

View File

@ -1,3 +1,18 @@
# 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
```

View File

@ -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

81
keepalive/keepalive.py Normal file
View File

@ -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)

View File

14
keepalive/lib/hf.py Normal file
View File

@ -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

View File

@ -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")

View File

@ -0,0 +1,5 @@
undetected-chromedriver
selenium==4.9.1
huggingface_hub
webdriver_manager
pyvirtualdisplay

View File

@ -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)

25
space/Dockerfile Normal file
View File

@ -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

14
space/server.py Normal file
View File

@ -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)

30
space/supervisord.conf Normal file
View File

@ -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