staging & TODO
This commit is contained in:
parent
7ca23a2ff4
commit
c257844fa2
|
@ -0,0 +1,5 @@
|
|||
[ ] Fully implement and test proxies
|
||||
[ ] Add a counter of tries for a captcha
|
||||
[ ] Make new setting "max tries per captcha"
|
||||
[ ] Unclaim proxy and delete captcha on max tries reached
|
||||
[ ] Add retry to fronted when captcha is entered incorrectly
|
|
@ -1,5 +1,18 @@
|
|||
CREATE TABLE IF NOT EXISTS captchas(
|
||||
CREATE TABLE IF NOT EXISTS captchas (
|
||||
id SERIAL PRIMARY KEY,
|
||||
proxy_id INTEGER REFERENCES proxies(id),
|
||||
hash CHAR(32),
|
||||
solution CHAR(6)
|
||||
);
|
||||
);
|
||||
|
||||
CREATE TYPE IF NOT EXISTS protocol_type AS ENUM ('http', 'https');
|
||||
|
||||
CREATE TABLE IF NOT EXISTS proxies (
|
||||
id SERIAL PRIMARY KEY,
|
||||
proto protocol_type,
|
||||
claimed BOOLEAN DEFAULT FALSE,
|
||||
host INET NOT NULL,
|
||||
port SMALLINT NOT NULL,
|
||||
username VARCHAR(16),
|
||||
password VARCHAR(32)
|
||||
)
|
|
@ -1,5 +1,5 @@
|
|||
window.onload = async () => {
|
||||
let id = (await (await fetch("/api/captcha/new", {method: "POST"})).json()).id
|
||||
let id = (await (await fetch("/api/captcha", {method: "POST"})).json()).id
|
||||
console.log(id);
|
||||
fetch(`/api/captcha/${id}`).then(response => response.blob())
|
||||
.then(blob => {
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
import CaptchaService from "../services/captcha.js";
|
||||
import config from '../config.js';
|
||||
import fs from 'fs/promises';
|
||||
|
||||
class ApiController {
|
||||
async new(req, res) {
|
||||
const id = await CaptchaService.new();
|
||||
|
||||
return res.status(200).send({"id": id});
|
||||
}
|
||||
|
||||
async get(req, res) {
|
||||
const id = req.params.id;
|
||||
|
||||
const hash = await CaptchaService.get(id);
|
||||
if (hash == undefined) {
|
||||
return res.status(404).send({"message": "captcha not found"});
|
||||
}
|
||||
const image = await fs.readFile(`${config.data_dir}/${hash}.jpeg`);
|
||||
|
||||
return res.status(200).send(image)
|
||||
}
|
||||
|
||||
async solve (req, res) {
|
||||
const id = req.params.id;
|
||||
const solution = req.body["solution"];
|
||||
if (solution == undefined || solution.length != 6) {
|
||||
return res.status(400).send({"message": 'please, send a valid solution. Example: {"solution":"123456"}'});
|
||||
}
|
||||
|
||||
if (!await CaptchaService.check_and_save_solution(id, solution))
|
||||
return res.status(409).send({"message": "Solution is not correct"});
|
||||
|
||||
return res.status(200).send({"message": "Successful"});
|
||||
}
|
||||
}
|
||||
|
||||
export default new ApiController();
|
|
@ -0,0 +1,57 @@
|
|||
import CaptchaService from "../services/captcha.js";
|
||||
import ProxyService from "../services/proxy.js";
|
||||
import config from '../config.js';
|
||||
import fs from 'fs/promises';
|
||||
|
||||
class CaptchaController {
|
||||
async new(req, res) {
|
||||
try {
|
||||
const proxy = await ProxyService.take();
|
||||
const id = await CaptchaService.new(proxy);
|
||||
|
||||
return res.status(200).send({"id": id});
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
return res.status(500).send({"message": "Unknown server error"});
|
||||
}
|
||||
}
|
||||
|
||||
async get(req, res) {
|
||||
try {
|
||||
const id = req.params.id;
|
||||
|
||||
const hash = await CaptchaService.get(id);
|
||||
if (hash == undefined) {
|
||||
return res.status(404).send({"message": "captcha not found"});
|
||||
}
|
||||
const image = await fs.readFile(`${config.data_dir}/${hash}.jpeg`);
|
||||
|
||||
return res.status(200).send(image)
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
return res.status(500).send({"message": "Unknown server error"});
|
||||
}
|
||||
}
|
||||
|
||||
async solve (req, res) {
|
||||
try {
|
||||
const id = req.params.id;
|
||||
const solution = req.body["solution"];
|
||||
if (solution == undefined || solution.length != 6) {
|
||||
return res.status(400).send({"message": 'please, send a valid solution. Example: {"solution":"123456"}'});
|
||||
}
|
||||
|
||||
if (!await CaptchaService.check_and_save_solution(id, solution))
|
||||
return res.status(409).send({"message": "Solution is not correct"});
|
||||
|
||||
let proxy_id = await CaptchaService.get_assigned_proxy(id);
|
||||
await ProxyService.give_back(id);
|
||||
return res.status(200).send({"message": "Successful"});
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
return res.status(500).send({"message": "Unknown server error"});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new CaptchaController();
|
|
@ -0,0 +1,31 @@
|
|||
import ProxyService from '../services/proxy.js';
|
||||
|
||||
class CaptchaController {
|
||||
async add(req, res) {
|
||||
try {
|
||||
const { host, port, user: username, password } = req.body;
|
||||
if (!host || !port) return res.status(400).send({"message":"You must specify host and port!"});
|
||||
|
||||
const id = await ProxyService.add(host, port, username, password);
|
||||
|
||||
return res.status(200).send({"id": id});
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
return res.status(500).send({"message": "Unknown server error"});
|
||||
}
|
||||
}
|
||||
|
||||
async delete (req, res) {
|
||||
try {
|
||||
const id = req.params.id;
|
||||
await ProxyService.delete(id)
|
||||
return res.status(200).send({"message": "Successful"});
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
return res.status(500).send({"message": "Unknown server error"});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export default new CaptchaController();
|
|
@ -1,7 +1,7 @@
|
|||
import express from 'express';
|
||||
import path from 'path';
|
||||
|
||||
import ApiRouter from './routers/api.js';
|
||||
import CaptchaRouter from './routers/captcha.js';
|
||||
import FrontendRouter from './routers/frontend.js';
|
||||
|
||||
import config from './config.js';
|
||||
|
@ -14,7 +14,7 @@ app.use(express.json());
|
|||
|
||||
app.set('view engine', 'pug');
|
||||
|
||||
app.use('/api', ApiRouter);
|
||||
app.use('/api', CaptchaRouter);
|
||||
app.use('/', FrontendRouter);
|
||||
|
||||
const server = app.listen(config.app_port, () => {
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
import { Router } from 'express';
|
||||
|
||||
import ApiController from '../controllers/api.js';
|
||||
|
||||
const ApiRouter = new Router();
|
||||
|
||||
ApiRouter.post('/captcha/new', ApiController.new);
|
||||
ApiRouter.get('/captcha/:id', ApiController.get);
|
||||
ApiRouter.patch('/captcha/:id', ApiController.solve);
|
||||
|
||||
export default ApiRouter;
|
|
@ -0,0 +1,11 @@
|
|||
import { Router } from 'express';
|
||||
|
||||
import CaptchaController from '../controllers/captcha.js';
|
||||
|
||||
const CaptchaRouter = new Router();
|
||||
|
||||
CaptchaRouter.post('/captcha', CaptchaController.new);
|
||||
CaptchaRouter.get('/captcha/:id', CaptchaController.get);
|
||||
CaptchaRouter.patch('/captcha/:id', CaptchaController.solve);
|
||||
|
||||
export default CaptchaRouter;
|
|
@ -0,0 +1,11 @@
|
|||
import { Router } from 'express';
|
||||
|
||||
import ProxyController from '../controllers/proxy.js';
|
||||
|
||||
const ProxyRouter = new Router();
|
||||
|
||||
ProxyRouter.post('/proxy', ProxyController.add);
|
||||
ProxyRouter.get('/proxy/:id', ProxyController.get);
|
||||
ProxyRouter.patch('/captcha/:id', ProxyController.solve);
|
||||
|
||||
export default ProxyRouter;
|
|
@ -1,18 +1,26 @@
|
|||
import db from '../db.js';
|
||||
import fs from 'fs/promises';
|
||||
import { ProxyAgent } from 'undici';
|
||||
import config from '../config.js';
|
||||
import { createHash } from 'crypto';
|
||||
|
||||
|
||||
class CaptchaService {
|
||||
async new() {
|
||||
async new(proxy) {
|
||||
try {
|
||||
const captcha = await (await fetch(config.captcha_source_url)).blob();
|
||||
let dispatcher;
|
||||
if (proxy.username) {
|
||||
dispatcher = new ProxyAgent(`${proxy.proto}://${proxy.username}:${proxy.password}@${proxy.host}:${proxy.port}`)
|
||||
} else {
|
||||
dispatcher = new ProxyAgent(`${proxy.proto}://${proxy.host}:${proxy.port}`)
|
||||
}
|
||||
|
||||
const captcha = await (await fetch(config.captcha_source_url, dispatcher)).blob();
|
||||
const buffer = Buffer.from(await captcha.arrayBuffer());
|
||||
const hash = createHash('md5').update(buffer).digest('hex');
|
||||
await fs.writeFile(`${config.data_dir}/${hash}.jpeg`, buffer);
|
||||
|
||||
const id = (await db.query("INSERT INTO captchas (hash) VALUES ($1) RETURNING id", [hash])).rows[0].id;
|
||||
const id = (await db.query("INSERT INTO captchas (hash, proxy_id) VALUES ($1, $2) RETURNING id", [hash, proxy.id])).rows[0].id;
|
||||
|
||||
return id
|
||||
} catch(e) {
|
||||
|
@ -56,6 +64,10 @@ class CaptchaService {
|
|||
await db.query("UPDATE captchas SET solution = $1 WHERE id = $2", [solution, id]);
|
||||
return true;
|
||||
}
|
||||
|
||||
async get_assigned_proxy(id) {
|
||||
return (await db.query("SELECT proxy_id FROM captchas WHERE id = $1", [id])).rows[0].proxy_id;
|
||||
}
|
||||
}
|
||||
|
||||
export default new CaptchaService();
|
|
@ -0,0 +1,23 @@
|
|||
import db from '../db.js';
|
||||
|
||||
class ProxyService {
|
||||
async add(proto, host, port, username, password) {
|
||||
await db.query("INSERT INTO proxies (proto, host, port, username, password) VALUES ($1, $2, $3, $4, $5)", [proto, host, port, username, password]);
|
||||
}
|
||||
|
||||
async take() {
|
||||
let proxy = (await db.query("UPDATE proxies SET claimed = TRUE WHERE id = ( SELECT id FROM proxies WHERE claimed = FALSE ORDER BY id LIMIT 1 ) RETURNING proto, host, port, username, password")).rows[0]
|
||||
if (proxy == undefined) return undefined;
|
||||
return proxy;
|
||||
}
|
||||
|
||||
async give_back(id) {
|
||||
await db.query("UPDATE proxies SET claimed = false WHERE id = $1", [id]);
|
||||
}
|
||||
|
||||
async delete(id) {
|
||||
await db.query("DELETE FRM proxies WHERE id = $1", [id]);
|
||||
}
|
||||
}
|
||||
|
||||
export default new ProxyService();
|
Loading…
Reference in New Issue