Spaces:
Runtime error
Runtime error
import { Request, Response } from "express"; | |
import * as textToImage from 'text-to-image'; | |
import showdown from "showdown"; | |
import { config, listConfig } from "./config"; | |
import { keys } from "./keys"; | |
import { proxies } from "./proxies"; | |
import { captchas } from './proxy/captchas'; | |
import { proxyKeys } from './proxy/proxy-keys'; | |
import { getUniqueIps } from "./proxy/rate-limit"; | |
export const handleInfoPage = async (req: Request, res: Response) => { | |
// Huggingface puts spaces behind some cloudflare ssl proxy, so `req.protocol` is `http` but the correct URL is actually `https` | |
const host = req.get("host"); | |
const isHuggingface = host?.includes("hf.space"); | |
const protocol = isHuggingface ? "https" : req.protocol; | |
res.send(await getInfoPageHtml(protocol + "://" + host, req.body)); | |
}; | |
const ms = require('ms'); | |
async function getInfoPageHtml(host: string, body: any) { | |
const keylist = keys.list(); | |
const proxylist = proxies.list(); | |
const rateLimitInfo = { proompters: getUniqueIps() }; | |
const usage = keys.getUsage(); | |
const now = Date.now(); | |
const uptimeDays = Math.floor(process.uptime() / 86400); | |
const info = { | |
uptime: uptimeDays > 0 ? `${uptimeDays} день или дня или дней` : 'меньше дня', | |
timestamp: new Date(now).toLocaleString('ru-RU', { timeZone: 'Europe/Moscow' }), | |
api: host + "/proxy/openai/v1", | |
proompts: keylist.reduce((acc, k) => acc + k.promptCount, 0) + proxylist.reduce((acc, k) => acc + k.promptCount, 0), | |
...(config.modelRateLimit ? rateLimitInfo : {}), | |
'gpt-3.5-turbo': { | |
all: keylist.length, | |
active: keylist.filter((k) => !k.isDisabled).length, | |
trial: keylist.filter((k) => k.isTrial && !k.isDisabled).length, | |
remaining: usage.gpt3.remaining, | |
usage: `${usage.gpt3.usage.toFixed(2)}/${Math.round(usage.gpt3.limit)}`, | |
}, | |
'gpt-4': { | |
all: keylist.filter((k) => k.isGpt4).length, | |
active: keylist.filter((k) => k.isGpt4 && !k.isDisabled).length, | |
trial: keylist.filter((k) => k.isGpt4 && k.isTrial && !k.isDisabled).length, | |
remaining: usage.gpt4.remaining, | |
usage: `${usage.gpt4.usage.toFixed(2)}/${Math.round(usage.gpt4.limit)}`, | |
}, | |
config: listConfig(), | |
}; | |
const readme = require("fs").readFileSync("README.md", "utf8"); | |
const readmeBody = readme.split("---")[2] || readme; | |
const converter = new showdown.Converter(); | |
const html = converter.makeHtml(readmeBody); | |
let captchaHTML = ''; | |
if (config.proxyCaptcha) { | |
if (captchas.check(body?.key, body?.value)) { | |
const key = proxyKeys.generate(); | |
captchaHTML = ` | |
<p style="text-align: center;color: #fff;"> | |
Твой ключ от прокси - <code>${key}</code><br /> | |
Писать его в поле API Key в таверне и не забудь после этого нажать Connect. <br /> | |
Учти, если превысишь лимит в ${config.modelRateLimit} запросов в минуту - ключ превратится в тыкву и придётся идти за новым. | |
</p> | |
`; | |
} else { | |
const captcha = await captchas.generate(); | |
captchaHTML = ` | |
<img src="${captcha.instructionImg}"/><br /> | |
<img src="${captcha.img}"/><br /> | |
<div style="display: grid;width: 33%;"> | |
<input type="hidden" name="key" value="${captcha.key}" /> | |
<input type="text" name="value" autocomplete="off" /> | |
<input type="submit" value="${captchas.encodeString('Нажатием этой кнопки вы поддерживаете СВО')}" /> | |
</div> | |
<script> | |
const form = document.getElementById("captchaForm"); | |
document.addEventListener('keyup', (e) => { | |
if (e.ctrlKey) form?.reset(); | |
}); | |
document.addEventListener('mousedown', (e) => { | |
if (e.button === 2) form?.reset(); | |
}); | |
</script> | |
`; | |
} | |
} | |
const pageBody = `<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8" /> | |
<title>2ch proxy.</title> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> | |
</head> | |
<body style="padding: 1em;"> | |
<main> | |
${html} | |
<div style="width: 100%;height: 47px;content: "Z";margin-left: auto;margin-right: auto;color: #f9f946;font-size: 36px;background: linear-gradient(to bottom, #000 33.333%, #0039A6 33.333%, #0039A6 66.667%, #D52B1E 66.667%);text-shadow: 1px 2px 1px black;font-family: initial;text-align: center;margin-bottom: 9px;">Z</div> | |
<form action="" method="POST" style="margin-left:auto;margin-right:auto;" id="captchaForm"> | |
${captchaHTML} | |
<pre>${JSON.stringify(info, null, 2)}</pre> | |
</form> | |
<div style="width: 100%;height: 47px;content: "Z";margin-left: auto;margin-right: auto;color: #f9f946;font-size: 36px;background: linear-gradient(to bottom, #64C8FF 33.333%, #0039A6 33.333%, #0039A6 66.667%, #D52B1E 66.667%);text-shadow: 1px 2px 1px black;font-family: initial;text-align: center;margin-top: 9px;">V</div> | |
<div style="position:absolute; top:-9999px; left:-9999px;"> | |
<div id="player"></div> | |
</div> | |
</main> | |
</body> | |
<script> | |
var player; | |
var videoIds = ['nClPPq2s-XQ', 'I8EMtklElRE', 'paZxfm8dhG0', 'OcdZtfuSt_A', 'AcTnMR_boys', 'i-DeuCQqgkM', '5qNtOryEVc0', 'pvq1NQz-I5E', 'm7FKzjmeg8U', 'mzaf8ExJ2hg', 'wOTD2KaAVjc', '5d1HWklOlN8', 'sYMZtGsDzss' ]; | |
// Замените VIDEO_ID на реальные ID видео, которые вы хотите проигрывать | |
function onYouTubeIframeAPIReady() { | |
var randomIndex = Math.floor(Math.random() * videoIds.length); | |
var randomVideoId = videoIds[randomIndex]; | |
player = new YT.Player('player', { | |
videoId: randomVideoId, | |
playerVars: { | |
autoplay: 1, | |
loop: 1, | |
controls: 1, | |
showinfo: 1, | |
modestbranding: 1, | |
iv_load_policy: 3, | |
start: 1, | |
autohide: 0, | |
mute: 0 | |
}, | |
events: { | |
'onReady': onPlayerReady | |
} | |
}); | |
} | |
function onPlayerReady(event) { | |
event.target.playVideo(); | |
} | |
var tag = document.createElement('script'); | |
tag.src = "https://www.youtube.com/iframe_api"; | |
var firstScriptTag = document.getElementsByTagName('script')[0]; | |
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); | |
</script> | |
<style> | |
pre{ | |
border-radius: 8px; | |
background: #222; | |
width: 31%; | |
margin-left: auto; | |
margin-right: auto; | |
overflow: auto; | |
padding: 11px; | |
border: double; | |
text-align: start; | |
font-size: 11px; | |
color: #fff; | |
user-select: text; | |
} | |
body { | |
background-color: #222!important; | |
display: block; | |
margin-left: auto; | |
margin-right: auto; | |
} | |
#captchaForm { | |
display: flex; | |
flex-direction: column; | |
align-items: center; | |
margin: 6px; | |
margin-left: auto; | |
margin-right: auto; | |
border-radius: 6px; | |
width: 66%; | |
} | |
img { | |
margin: 5px; | |
margin-left:auto; | |
margin-right:auto; | |
height: 40px; | |
} | |
input[type="text"]{ | |
border-top-left-radius: 6px; | |
border: 0px; | |
border-top-right-radius: 6px; | |
background-color: #333; | |
color: #fff; | |
padding: 7px; | |
text-align: center; | |
} | |
input[type="submit"]{ | |
border-bottom-left-radius: 6px; | |
border: 0px; | |
border-bottom-right-radius: 6px; | |
background-color: #373636; | |
color: #fff; | |
padding: 7px; | |
text-align: center; | |
} | |
form { | |
user-select: text; | |
display: grid; | |
border: #fff 2px double; | |
margin: 5px; | |
margin-right: 5px; | |
margin-left: 5px; | |
padding: 11px; | |
border-radius: 6px; | |
margin-left: auto; | |
margin-right: auto; | |
} | |
input:hover { | |
background-color: #242424!important; | |
cursor: pointer; | |
} | |
</style> | |
</html>`; | |
return pageBody; | |
} |