mirror of
https://github.com/simon987/imhashdb.git
synced 2025-04-04 02:22:58 +00:00
213 lines
4.5 KiB
Go
213 lines
4.5 KiB
Go
package imhashdb
|
|
|
|
import (
|
|
"encoding/json"
|
|
"github.com/go-redis/redis/v7"
|
|
"github.com/jackc/pgx"
|
|
"github.com/pkg/errors"
|
|
"github.com/simon987/fastimagehash-go"
|
|
"github.com/valyala/fasthttp"
|
|
"go.uber.org/zap"
|
|
"strings"
|
|
)
|
|
|
|
const UserAgent = "imhashdb/v1.0"
|
|
|
|
var ImageSuffixes = []string{
|
|
".jpeg", ".jpg", ".png",
|
|
".jpeg:orig", ".jpg:orig", ".png:orig",
|
|
".bmp", ".webp",
|
|
}
|
|
|
|
type Config struct {
|
|
PgUser string
|
|
PgPassword string
|
|
PgDb string
|
|
PgHost string
|
|
PgPort int
|
|
|
|
RedisAddr string
|
|
RedisPassword string
|
|
RedisDb int
|
|
|
|
ApiAddr string
|
|
|
|
HasherConcurrency int
|
|
QueryConcurrency int
|
|
|
|
Store string
|
|
|
|
ImgurClientId string
|
|
HasherPattern string
|
|
}
|
|
|
|
var ImageBlackList = []string{}
|
|
|
|
var Rdb *redis.Client
|
|
var Pgdb *pgx.ConnPool
|
|
var Logger *zap.Logger
|
|
var Conf Config
|
|
|
|
func Init() {
|
|
Logger, _ = zap.NewDevelopment()
|
|
|
|
Rdb = redis.NewClient(&redis.Options{
|
|
Addr: Conf.RedisAddr,
|
|
Password: Conf.RedisPassword,
|
|
DB: Conf.RedisDb,
|
|
})
|
|
_, err := Rdb.Ping().Result()
|
|
if err != nil {
|
|
Logger.Fatal("Could not connect to redis server")
|
|
}
|
|
|
|
Pgdb = DbConnect(
|
|
Conf.PgHost,
|
|
Conf.PgPort,
|
|
Conf.PgUser,
|
|
Conf.PgPassword,
|
|
Conf.PgDb,
|
|
)
|
|
DbInit(Pgdb)
|
|
}
|
|
|
|
func ComputeHash(data []byte) (*Hashes, error) {
|
|
h := &Hashes{}
|
|
var code fastimagehash.Code
|
|
|
|
h.DHash8, code = fastimagehash.DHashMem(data, 8)
|
|
if code != fastimagehash.Ok {
|
|
return nil, errors.Errorf("dHash error: %d", int(code))
|
|
}
|
|
h.DHash16, code = fastimagehash.DHashMem(data, 16)
|
|
if code != fastimagehash.Ok {
|
|
return nil, errors.Errorf("dHash error: %d", int(code))
|
|
}
|
|
h.DHash32, code = fastimagehash.DHashMem(data, 32)
|
|
if code != fastimagehash.Ok {
|
|
return nil, errors.Errorf("dHash error: %d", int(code))
|
|
}
|
|
|
|
h.MHash8, code = fastimagehash.MHashMem(data, 8)
|
|
if code != fastimagehash.Ok {
|
|
return nil, errors.Errorf("mHash error: %d", int(code))
|
|
}
|
|
h.MHash16, code = fastimagehash.MHashMem(data, 16)
|
|
if code != fastimagehash.Ok {
|
|
return nil, errors.Errorf("mHash error: %d", int(code))
|
|
}
|
|
h.MHash32, code = fastimagehash.MHashMem(data, 32)
|
|
if code != fastimagehash.Ok {
|
|
return nil, errors.Errorf("mHash error: %d", int(code))
|
|
}
|
|
|
|
h.PHash8, code = fastimagehash.PHashMem(data, 8, 4)
|
|
if code != fastimagehash.Ok {
|
|
return nil, errors.Errorf("pHash error: %d", int(code))
|
|
}
|
|
h.PHash16, code = fastimagehash.PHashMem(data, 16, 4)
|
|
if code != fastimagehash.Ok {
|
|
return nil, errors.Errorf("pHash error: %d", int(code))
|
|
}
|
|
h.PHash32, code = fastimagehash.PHashMem(data, 32, 4)
|
|
if code != fastimagehash.Ok {
|
|
return nil, errors.Errorf("pHash error: %d", int(code))
|
|
}
|
|
|
|
h.WHash8, code = fastimagehash.WHashMem(data, 8, 0, true, fastimagehash.Haar)
|
|
if code != fastimagehash.Ok {
|
|
return nil, errors.Errorf("wHash error: %d", int(code))
|
|
}
|
|
h.WHash16, code = fastimagehash.WHashMem(data, 16, 0, true, fastimagehash.Haar)
|
|
if code != fastimagehash.Ok {
|
|
return nil, errors.Errorf("wHash error: %d", int(code))
|
|
}
|
|
h.WHash32, code = fastimagehash.WHashMem(data, 32, 0, true, fastimagehash.Haar)
|
|
if code != fastimagehash.Ok {
|
|
return nil, errors.Errorf("wHash error: %d", int(code))
|
|
}
|
|
|
|
return h, nil
|
|
}
|
|
|
|
func TransformLink(link string, meta *[]Meta) []string {
|
|
for _, str := range ImageBlackList {
|
|
if strings.Contains(link, str) {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
links := handleImgurLink(link, meta)
|
|
if links != nil {
|
|
return links
|
|
}
|
|
|
|
return []string{link}
|
|
}
|
|
func isHttpOk(code int) bool {
|
|
return code >= 200 && code < 300
|
|
}
|
|
|
|
func FetchJson(link string, v interface{}, raw *[]byte, headers ...[]string) error {
|
|
|
|
body, err := Fetch(link, headers...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = json.Unmarshal(body, v)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
*raw = body
|
|
|
|
return nil
|
|
}
|
|
|
|
func Fetch(link string, headers ...[]string) ([]byte, error) {
|
|
client := &fasthttp.Client{}
|
|
|
|
req := fasthttp.AcquireRequest()
|
|
defer fasthttp.ReleaseRequest(req)
|
|
req.SetRequestURI(link)
|
|
req.Header.Add("User-Agent", UserAgent)
|
|
for _, h := range headers {
|
|
req.Header.Add(h[0], h[1])
|
|
}
|
|
|
|
resp := fasthttp.AcquireResponse()
|
|
defer fasthttp.ReleaseResponse(resp)
|
|
err := client.Do(req, resp)
|
|
|
|
if err != nil {
|
|
Logger.Warn(
|
|
"Error during HTTP request",
|
|
zap.String("link", link),
|
|
zap.String("err", err.Error()),
|
|
)
|
|
return nil, err
|
|
}
|
|
|
|
code := resp.StatusCode()
|
|
if !isHttpOk(code) {
|
|
Logger.Debug(
|
|
"Got HTTP error code",
|
|
zap.String("link", link),
|
|
zap.Int("code", code),
|
|
)
|
|
return nil, errors.Errorf("HTTP %d", code)
|
|
}
|
|
|
|
body := make([]byte, len(resp.Body()))
|
|
copy(body, resp.Body())
|
|
|
|
Logger.Debug(
|
|
"HTTP Get",
|
|
zap.String("link", link),
|
|
zap.Int("size", len(body)),
|
|
)
|
|
|
|
return body, nil
|
|
}
|