mirror of
https://codeberg.org/pluja/kycnot.me
synced 2025-01-08 21:57:58 -05:00
remove old named files
This commit is contained in:
parent
240f6c9cd1
commit
2a26a3d35b
@ -1,179 +0,0 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/draw"
|
||||
"image/png"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/freetype"
|
||||
"github.com/golang/freetype/truetype"
|
||||
"github.com/kataras/iris/v12"
|
||||
"github.com/rs/zerolog/log"
|
||||
"golang.org/x/image/font"
|
||||
"golang.org/x/image/font/gofont/gomonobold"
|
||||
|
||||
"pluja.dev/kycnot.me/database"
|
||||
)
|
||||
|
||||
func (s *Server) handleVerifyPow(c iris.Context) {
|
||||
// Get id, nonce and proof from the request
|
||||
id := c.Params().Get("id")
|
||||
nonce := c.Params().Get("nonce")
|
||||
|
||||
// Verify the proof of work
|
||||
valid := s.PowChallenger.PowVerifyProof(id, nonce)
|
||||
|
||||
// Return the result
|
||||
c.JSON(iris.Map{
|
||||
"valid": valid,
|
||||
"status": iris.StatusOK,
|
||||
})
|
||||
}
|
||||
|
||||
// Proxies the request to the logo URL of a service by its ID
|
||||
func (s *Server) handleApiPicture(c iris.Context) {
|
||||
id := c.Params().Get("id")
|
||||
|
||||
service, err := database.Pb.GetServiceById(id)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Could not get service")
|
||||
respondWithPlaceholder(c, "?")
|
||||
return
|
||||
}
|
||||
|
||||
if service.LogoURL == "" {
|
||||
log.Debug().Msgf("Image %s not found in cache", service.ID)
|
||||
respondWithPlaceholder(c, service.Name)
|
||||
return
|
||||
}
|
||||
|
||||
if imageData, err := s.Cache.Get(fmt.Sprintf("img-%s", service.ID)); err == nil {
|
||||
log.Debug().Msgf("Found image %s in cache", service.ID)
|
||||
ctt, _ := s.Cache.Get(fmt.Sprintf("ctt-%s", service.ID))
|
||||
c.ContentType(string(ctt))
|
||||
c.StatusCode(iris.StatusOK)
|
||||
c.Write(imageData)
|
||||
return
|
||||
}
|
||||
|
||||
log.Debug().Msgf("Image %s not found in cache", service.ID)
|
||||
client := &http.Client{}
|
||||
req, err := http.NewRequest("GET", service.LogoURL, nil)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Failed to create HTTP request")
|
||||
return
|
||||
}
|
||||
|
||||
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.3")
|
||||
req.Header.Set("Referer", service.Urls[0])
|
||||
resp, err := client.Do(req)
|
||||
if err != nil || resp.StatusCode != http.StatusOK {
|
||||
log.Error().Err(err).Msg("Could not get image")
|
||||
respondWithPlaceholder(c, service.Name)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
bodyBytes, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Could not read response body")
|
||||
respondWithPlaceholder(c, service.Name)
|
||||
return
|
||||
}
|
||||
|
||||
if bodyBytes == nil {
|
||||
log.Error().Msg("Could not read response body")
|
||||
respondWithPlaceholder(c, service.Name)
|
||||
return
|
||||
}
|
||||
|
||||
s.Cache.Set(fmt.Sprintf("img-%s", service.ID), bodyBytes)
|
||||
s.Cache.Set(fmt.Sprintf("ctt-%s", service.ID), []byte(resp.Header.Get("Content-Type")))
|
||||
|
||||
c.ContentType(resp.Header.Get("Content-Type"))
|
||||
c.StatusCode(iris.StatusOK)
|
||||
c.Write(bodyBytes)
|
||||
}
|
||||
|
||||
func respondWithPlaceholder(c iris.Context, serviceName string) {
|
||||
log.Debug().Msgf("Generating placeholder for %s", serviceName)
|
||||
const width, height = 250, 250
|
||||
const margin = 15
|
||||
firstLetter := strings.ToUpper(string(serviceName[0]))
|
||||
|
||||
// Create an image
|
||||
img := image.NewRGBA(image.Rect(0, 0, width, height))
|
||||
|
||||
// Set background to black
|
||||
draw.Draw(img, img.Bounds(), image.NewUniform(color.Black), image.Point{}, draw.Src)
|
||||
|
||||
// Load the monospace font
|
||||
f, err := truetype.Parse(gomonobold.TTF)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("could not parse font")
|
||||
return
|
||||
}
|
||||
|
||||
// Initialize freetype context
|
||||
ctx := freetype.NewContext()
|
||||
ctx.SetDPI(72)
|
||||
ctx.SetFont(f)
|
||||
|
||||
// Parse hex color and set text color
|
||||
var r, g, b uint8
|
||||
hexColor := "#84cc16"
|
||||
_, err = fmt.Sscanf(hexColor, "#%02x%02x%02x", &r, &g, &b)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Invalid hex color")
|
||||
return
|
||||
}
|
||||
textColor := color.RGBA{R: r, G: g, B: b, A: 255}
|
||||
ctx.SetSrc(image.NewUniform(textColor))
|
||||
|
||||
ctx.SetClip(img.Bounds())
|
||||
ctx.SetDst(img)
|
||||
|
||||
// Dynamically calculate the maximum font size
|
||||
var fontSize float64
|
||||
var textWidth, textHeight int
|
||||
for fontSize = 205; fontSize > 10; fontSize -= 0.5 {
|
||||
ctx.SetFontSize(fontSize)
|
||||
opts := truetype.Options{Size: fontSize}
|
||||
face := truetype.NewFace(f, &opts)
|
||||
textWidth = font.MeasureString(face, firstLetter).Round()
|
||||
ascent, descent := face.Metrics().Ascent, face.Metrics().Descent
|
||||
textHeight = (ascent + descent).Ceil()
|
||||
|
||||
if textWidth <= width-margin*2 && textHeight <= height-margin*2 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate position for the text
|
||||
x := (width - textWidth) / 2
|
||||
y := (height-textHeight)/2 + textHeight - int(ctx.PointToFixed(fontSize*0.2)>>6)
|
||||
pt := freetype.Pt(x, y)
|
||||
|
||||
// Draw the text
|
||||
if _, err := ctx.DrawString(firstLetter, pt); err != nil {
|
||||
log.Error().Err(err).Msg("Failed to draw string")
|
||||
return
|
||||
}
|
||||
|
||||
// Encode to PNG
|
||||
var buf bytes.Buffer
|
||||
if err := png.Encode(&buf, img); err != nil {
|
||||
log.Error().Err(err).Msg("Failed to encode image")
|
||||
return
|
||||
}
|
||||
|
||||
c.ContentType("image/png")
|
||||
c.StatusCode(iris.StatusOK)
|
||||
c.Write(buf.Bytes())
|
||||
}
|
@ -1,324 +0,0 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"strings"
|
||||
|
||||
"github.com/kataras/iris/v12"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"pluja.dev/kycnot.me/database"
|
||||
"pluja.dev/kycnot.me/utils"
|
||||
)
|
||||
|
||||
func (s *Server) handleIndex(c iris.Context) {
|
||||
nokycPf := []string{
|
||||
"KYC-Free Crypto Freedom.",
|
||||
"Goodbye KYC, hello privacy.",
|
||||
"KYC is a scam. Don't fall for it.",
|
||||
}
|
||||
|
||||
t := c.URLParam("t")
|
||||
q := c.URLParam("q")
|
||||
|
||||
// Currencies
|
||||
xmr := c.URLParam("xmr")
|
||||
btc := c.URLParam("btc")
|
||||
ln := c.URLParam("ln")
|
||||
cash := c.URLParam("cash")
|
||||
fiat := c.URLParam("fiat")
|
||||
|
||||
filters := []string{"(listed=true && pending=false)"}
|
||||
|
||||
if t != "" && t != "all" {
|
||||
filters = append(filters, fmt.Sprintf("(type='%v')", t))
|
||||
}
|
||||
|
||||
if q != "" {
|
||||
filters = append(
|
||||
filters,
|
||||
fmt.Sprintf("(name~'%v' || description~'%v' || tags~'%v')", q, q, q),
|
||||
)
|
||||
}
|
||||
|
||||
if xmr != "" {
|
||||
filters = append(filters, fmt.Sprintf("(xmr=%v)", xmr == "on"))
|
||||
}
|
||||
if btc != "" {
|
||||
filters = append(filters, fmt.Sprintf("(btc=%v)", btc == "on"))
|
||||
}
|
||||
if ln != "" {
|
||||
filters = append(filters, fmt.Sprintf("(lightning=%v)", ln == "on"))
|
||||
}
|
||||
if cash != "" {
|
||||
filters = append(filters, fmt.Sprintf("(cash=%v)", cash == "on"))
|
||||
}
|
||||
if fiat != "" {
|
||||
filters = append(filters, fmt.Sprintf("(fiat=%v)", fiat == "on"))
|
||||
}
|
||||
|
||||
services, err := database.Pb.GetServices(
|
||||
fmt.Sprintf("(%v)", strings.Join(filters, " && ")),
|
||||
"score,@random",
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Could not get services from Pocketbase")
|
||||
c.HTML("<h3>%s</h3>", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ViewLayout("main")
|
||||
data := iris.Map{
|
||||
"Title": "Home",
|
||||
"Filters": map[string]string{
|
||||
"Type": t,
|
||||
"Query": q,
|
||||
"Xmr": xmr,
|
||||
"Btc": btc,
|
||||
"Ln": ln,
|
||||
"Cash": cash,
|
||||
"Fiat": fiat,
|
||||
},
|
||||
"Current": "index",
|
||||
"Services": services,
|
||||
"RandomPitch": nokycPf[rand.Intn(len(nokycPf))],
|
||||
}
|
||||
if err := c.View("index", data); err != nil {
|
||||
c.HTML("<h3>%s</h3>", err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) handleService(c iris.Context) {
|
||||
serviceName := strings.ToLower(c.Params().Get("name"))
|
||||
|
||||
service, err := database.Pb.GetServiceByNameOrUrl(serviceName)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msgf("Could not get service %v from database", serviceName)
|
||||
c.HTML("<h3>%s</h3>", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: Compute score in background when needed!
|
||||
// Update score in background
|
||||
//upd := c.URLParam("update", "")
|
||||
//if upd == "true" {
|
||||
// go utils.UpdateScore(service)
|
||||
//}
|
||||
//utils.ComputeScore(service)
|
||||
|
||||
c.ViewLayout("main")
|
||||
data := iris.Map{
|
||||
"Title": fmt.Sprintf("%v | Service", serviceName),
|
||||
"Service": service,
|
||||
"Attributes": service.Expand["attributes"],
|
||||
}
|
||||
if err := c.View("service", data); err != nil {
|
||||
c.HTML("<h3>%s</h3>", err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) handleAttribute(c iris.Context) {
|
||||
attributeId := strings.ToLower(c.Params().Get("id"))
|
||||
|
||||
// Get service from database by name
|
||||
attribute, err := database.Pb.GetAttribute(attributeId)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msgf("Could not get attribute %v from database", attributeId)
|
||||
c.HTML("<h3>%s</h3>", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Get all services that have this attribute
|
||||
services, err := database.Pb.GetServices(
|
||||
fmt.Sprintf("(attributes~'%v')", attributeId),
|
||||
"score",
|
||||
)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msgf("Could not get services with attribute %v from database", attributeId)
|
||||
c.HTML("<h3>%s</h3>", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ViewLayout("main")
|
||||
data := iris.Map{
|
||||
"Title": fmt.Sprintf("%v", attribute.Title),
|
||||
"Attribute": attribute,
|
||||
"Services": services,
|
||||
}
|
||||
if err := c.View("attribute", data); err != nil {
|
||||
c.HTML("<h3>%s</h3>", err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) handleRequestServiceForm(c iris.Context) {
|
||||
challenge, id, difficulty, err := s.PowChallenger.PowGenerateChallenge(16)
|
||||
if err != nil {
|
||||
c.HTML("<h3>%s</h3>", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
attributes, err := database.Pb.GetAttributes("", "-rating")
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Could not get attributes from database")
|
||||
c.HTML("<h3>%s</h3>", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ViewLayout("main")
|
||||
data := iris.Map{
|
||||
"Title": "Request a service",
|
||||
"Current": "request",
|
||||
"Pow": map[string]interface{}{
|
||||
"Challenge": challenge,
|
||||
"Difficulty": difficulty,
|
||||
"Id": id,
|
||||
},
|
||||
"Attributes": attributes,
|
||||
"Error": c.URLParam("error"),
|
||||
"Message": c.URLParam("message"),
|
||||
}
|
||||
if err := c.View("request_service", data); err != nil {
|
||||
c.HTML("<h3>%s</h3>", err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) handleAbout(c iris.Context) {
|
||||
c.ViewLayout("main")
|
||||
data := iris.Map{
|
||||
"Title": "About",
|
||||
"Current": "about",
|
||||
}
|
||||
if err := c.View("about", data); err != nil {
|
||||
c.HTML("<h3>%s</h3>", err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) handlePending(c iris.Context) {
|
||||
services, err := database.Pb.GetServices("pending=true", "score")
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Could not get services from database")
|
||||
c.HTML("<h3>%s</h3>", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ViewLayout("main")
|
||||
data := iris.Map{
|
||||
"Title": "Pending",
|
||||
"Services": services,
|
||||
}
|
||||
if err := c.View("pending", data); err != nil {
|
||||
c.HTML("<h3>%s</h3>", err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
type RequestFormData struct {
|
||||
Type string `form:"type"`
|
||||
Category string `form:"category"`
|
||||
Name string `form:"name"`
|
||||
Description string `form:"description"`
|
||||
Urls string `form:"urls"`
|
||||
LogoUrl string `form:"logo_url"`
|
||||
TosUrls string `form:"tos_urls"`
|
||||
OnionUrls string `form:"onion_urls"`
|
||||
Tags string `form:"tags"`
|
||||
Xmr bool `form:"xmr"`
|
||||
Btc bool `form:"btc"`
|
||||
Ln bool `form:"ln"`
|
||||
Fiat bool `form:"fiat"`
|
||||
Cash bool `form:"cash"`
|
||||
KYCLevel int `form:"kyc_level"`
|
||||
Attributes []string `form:"attributes"`
|
||||
PowNonce string `form:"pow-nonce"`
|
||||
PowId string `form:"pow-id"`
|
||||
}
|
||||
|
||||
func (s *Server) handlePostRequestServiceForm(c iris.Context) {
|
||||
log.Info().Msg("Handling request service form")
|
||||
log.Debug().Msg("Handling request service form")
|
||||
var data RequestFormData
|
||||
if err := c.ReadForm(&data); err != nil {
|
||||
log.Debug().Err(err).Msg("Could not parse form data")
|
||||
c.Redirect("/request/service?error=Invalid%20Form", iris.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("Nonce: %v, ID: %v", data.PowNonce, data.PowId)
|
||||
if !s.PowChallenger.PowVerifyProof(data.PowId, data.PowNonce) {
|
||||
log.Debug().Msg("Invalid PoW")
|
||||
c.Redirect("/request/service?error=Invalid%20Captcha", iris.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
if data.KYCLevel < 0 || data.KYCLevel >= 4 {
|
||||
log.Debug().Msgf("Invalid KYC Level value: %v", c.FormValue("kyc_level"))
|
||||
c.Redirect("/request/service?error=Invalid%20KYC%20Level", iris.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
if len(data.Attributes) < 3 {
|
||||
log.Debug().Msgf("Invalid number of attributes: %v", len(data.Attributes))
|
||||
c.Redirect("/request/service?error=You%20must%20select%20at%20least%203%20attributes", iris.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
var service database.Service
|
||||
// Parse tags
|
||||
ts := strings.ReplaceAll(data.Tags, " ", ",")
|
||||
// Remove trailing commas
|
||||
ts = strings.TrimSuffix(ts, ",")
|
||||
// Remove duplicate commas
|
||||
ts = strings.ReplaceAll(ts, ",,", ",")
|
||||
// Remove leading commas
|
||||
ts = strings.TrimPrefix(ts, ",")
|
||||
// Convert to lowercase
|
||||
ts = strings.ToLower(ts)
|
||||
// Create tags array
|
||||
tags := strings.Split(ts, ",")
|
||||
|
||||
service.Tags = tags
|
||||
service.Name = strings.ToLower(data.Name)
|
||||
service.Description = data.Description
|
||||
service.LogoURL = utils.UrlParser(data.LogoUrl)
|
||||
service.Urls = utils.UrlListParser(data.Urls)
|
||||
service.TosUrls = utils.UrlListParser(data.TosUrls)
|
||||
service.OnionUrls = utils.UrlListParser(data.OnionUrls)
|
||||
service.Xmr = data.Xmr
|
||||
service.Btc = data.Btc
|
||||
service.Lightning = data.Ln
|
||||
service.Fiat = data.Fiat
|
||||
service.Cash = data.Cash
|
||||
service.Pending = true
|
||||
service.Listed = false
|
||||
service.Type = data.Type
|
||||
|
||||
if service.Type == "service" {
|
||||
service.Category = data.Category
|
||||
} else {
|
||||
service.Category = ""
|
||||
}
|
||||
|
||||
service.KycLevel = data.KYCLevel
|
||||
service.Attributes = data.Attributes
|
||||
|
||||
service.Score = utils.ComputeScore(&service)
|
||||
|
||||
// Save service to database
|
||||
err := database.Pb.CreateService(service)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Could not save service to database")
|
||||
c.Redirect("/request/service?error=internal-error", iris.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: Update score in background
|
||||
// go utils.UpdateScore(sv)
|
||||
c.Redirect("/request/service?message=Success!", iris.StatusSeeOther)
|
||||
}
|
Loading…
Reference in New Issue
Block a user