This commit is contained in:
qaq
2025-06-17 12:17:33 +08:00
parent 4a6b2c8e0f
commit 9fa968d07c
648 changed files with 64968 additions and 1621 deletions
+49
View File
@@ -0,0 +1,49 @@
package loader
import (
"bufio"
"bytes"
"context"
"io"
"os"
)
type fileLoader struct {
filename string
}
// FileLoader loads data from file.
func FileLoader(filename string) Loader {
return &fileLoader{
filename: filename,
}
}
func (l *fileLoader) Load(ctx context.Context) (io.Reader, error) {
data, err := os.ReadFile(l.filename)
if err != nil {
return nil, err
}
return bytes.NewReader(data), nil
}
// List implements Lister interface{}
func (l *fileLoader) List(ctx context.Context) (list []string, err error) {
f, err := os.Open(l.filename)
if err != nil {
return
}
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
list = append(list, scanner.Text())
}
err = scanner.Err()
return
}
func (l *fileLoader) Close() error {
return nil
}
+71
View File
@@ -0,0 +1,71 @@
package loader
import (
"bytes"
"context"
"fmt"
"io"
"net/http"
"time"
)
type httpLoaderOptions struct {
timeout time.Duration
}
type HTTPLoaderOption func(opts *httpLoaderOptions)
func TimeoutHTTPLoaderOption(timeout time.Duration) HTTPLoaderOption {
return func(opts *httpLoaderOptions) {
opts.timeout = timeout
}
}
type httpLoader struct {
url string
httpClient *http.Client
}
// HTTPLoader loads data from HTTP request.
func HTTPLoader(url string, opts ...HTTPLoaderOption) Loader {
var options httpLoaderOptions
for _, opt := range opts {
if opt != nil {
opt(&options)
}
}
return &httpLoader{
url: url,
httpClient: &http.Client{
Timeout: options.timeout,
},
}
}
func (l *httpLoader) Load(ctx context.Context) (io.Reader, error) {
req, err := http.NewRequest(http.MethodGet, l.url, nil)
if err != nil {
return nil, err
}
resp, err := l.httpClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("%d %s", resp.StatusCode, resp.Status)
}
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return bytes.NewReader(data), nil
}
func (l *httpLoader) Close() error {
return nil
}
+19
View File
@@ -0,0 +1,19 @@
package loader
import (
"context"
"io"
)
type Loader interface {
Load(context.Context) (io.Reader, error)
Close() error
}
type Lister interface {
List(ctx context.Context) ([]string, error)
}
type Mapper interface {
Map(ctx context.Context) (map[string]string, error)
}
+242
View File
@@ -0,0 +1,242 @@
package loader
import (
"bytes"
"context"
"fmt"
"io"
"strings"
"github.com/go-redis/redis/v8"
)
const (
DefaultRedisKey = "gost"
)
type redisLoaderOptions struct {
db int
username string
password string
key string
}
type RedisLoaderOption func(opts *redisLoaderOptions)
func DBRedisLoaderOption(db int) RedisLoaderOption {
return func(opts *redisLoaderOptions) {
opts.db = db
}
}
func UsernameRedisLoaderOption(username string) RedisLoaderOption {
return func(opts *redisLoaderOptions) {
opts.username = username
}
}
func PasswordRedisLoaderOption(password string) RedisLoaderOption {
return func(opts *redisLoaderOptions) {
opts.password = password
}
}
func KeyRedisLoaderOption(key string) RedisLoaderOption {
return func(opts *redisLoaderOptions) {
opts.key = key
}
}
type redisStringLoader struct {
client *redis.Client
key string
}
// RedisStringLoader loads data from redis string.
func RedisStringLoader(addr string, opts ...RedisLoaderOption) Loader {
var options redisLoaderOptions
for _, opt := range opts {
if opt != nil {
opt(&options)
}
}
key := options.key
if key == "" {
key = DefaultRedisKey
}
return &redisStringLoader{
client: redis.NewClient(&redis.Options{
Addr: addr,
Password: options.password,
DB: options.db,
}),
key: key,
}
}
func (p *redisStringLoader) Load(ctx context.Context) (io.Reader, error) {
v, err := p.client.Get(ctx, p.key).Bytes()
if err != nil {
return nil, err
}
return bytes.NewReader(v), nil
}
func (p *redisStringLoader) Close() error {
return p.client.Close()
}
type redisSetLoader struct {
client *redis.Client
key string
}
// RedisSetLoader loads data from redis set.
func RedisSetLoader(addr string, opts ...RedisLoaderOption) Loader {
var options redisLoaderOptions
for _, opt := range opts {
if opt != nil {
opt(&options)
}
}
key := options.key
if key == "" {
key = DefaultRedisKey
}
return &redisSetLoader{
client: redis.NewClient(&redis.Options{
Addr: addr,
Password: options.password,
DB: options.db,
}),
key: key,
}
}
func (p *redisSetLoader) Load(ctx context.Context) (io.Reader, error) {
v, err := p.List(ctx)
if err != nil {
return nil, err
}
return bytes.NewReader([]byte(strings.Join(v, "\n"))), nil
}
// List implements Lister interface{}
func (p *redisSetLoader) List(ctx context.Context) ([]string, error) {
return p.client.SMembers(ctx, p.key).Result()
}
func (p *redisSetLoader) Close() error {
return p.client.Close()
}
type redisListLoader struct {
client *redis.Client
key string
}
// RedisListLoader loads data from redis list.
func RedisListLoader(addr string, opts ...RedisLoaderOption) Loader {
var options redisLoaderOptions
for _, opt := range opts {
opt(&options)
}
key := options.key
if key == "" {
key = DefaultRedisKey
}
return &redisListLoader{
client: redis.NewClient(&redis.Options{
Addr: addr,
Password: options.password,
DB: options.db,
}),
key: key,
}
}
func (p *redisListLoader) Load(ctx context.Context) (io.Reader, error) {
v, err := p.List(ctx)
if err != nil {
return nil, err
}
return bytes.NewReader([]byte(strings.Join(v, "\n"))), nil
}
// List implements Lister interface{}
func (p *redisListLoader) List(ctx context.Context) ([]string, error) {
return p.client.LRange(ctx, p.key, 0, -1).Result()
}
func (p *redisListLoader) Close() error {
return p.client.Close()
}
type redisHashLoader struct {
client *redis.Client
key string
}
// RedisHashLoader loads data from redis hash.
func RedisHashLoader(addr string, opts ...RedisLoaderOption) Loader {
var options redisLoaderOptions
for _, opt := range opts {
opt(&options)
}
key := options.key
if key == "" {
key = DefaultRedisKey
}
return &redisHashLoader{
client: redis.NewClient(&redis.Options{
Addr: addr,
Password: options.password,
DB: options.db,
}),
key: key,
}
}
func (p *redisHashLoader) Load(ctx context.Context) (io.Reader, error) {
m, err := p.Map(ctx)
if err != nil {
return nil, err
}
var b strings.Builder
for k, v := range m {
fmt.Fprintf(&b, "%s %s\n", k, v)
}
return bytes.NewBufferString(b.String()), nil
}
// List implements Lister interface{}
func (p *redisHashLoader) List(ctx context.Context) (list []string, err error) {
m, err := p.Map(ctx)
if err != nil {
return
}
for k, v := range m {
list = append(list, fmt.Sprintf("%s %s", k, v))
}
return
}
// Map implements Mapper interface{}
func (p *redisHashLoader) Map(ctx context.Context) (map[string]string, error) {
return p.client.HGetAll(ctx, p.key).Result()
}
func (p *redisHashLoader) Close() error {
return p.client.Close()
}