mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-25 00:05:15 +00:00
Merge pull request #1763 from lanphan/obsoleted
CHORE: solved all deprecated, comment all unused variables and functions
This commit is contained in:
commit
b23c7a76eb
|
@ -2,7 +2,7 @@ package accounting
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -16,7 +16,7 @@ func TestStockManager(t *testing.T) {
|
|||
t.Run("testdata", func(t *testing.T) {
|
||||
var trades []types.Trade
|
||||
|
||||
out, err := ioutil.ReadFile("testdata/btcusdt-trades.json")
|
||||
out, err := os.ReadFile("testdata/btcusdt-trades.json")
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = json.Unmarshal(out, &trades)
|
||||
|
|
|
@ -136,12 +136,6 @@ func (e *Exchange) resetMatchingBooks() {
|
|||
e.matchingBooksMutex.Unlock()
|
||||
}
|
||||
|
||||
func (e *Exchange) addMatchingBook(symbol string, market types.Market) {
|
||||
e.matchingBooksMutex.Lock()
|
||||
e._addMatchingBook(symbol, market)
|
||||
e.matchingBooksMutex.Unlock()
|
||||
}
|
||||
|
||||
func (e *Exchange) _addMatchingBook(symbol string, market types.Market) {
|
||||
matching := &SimplePriceMatching{
|
||||
currentTime: e.currentTime,
|
||||
|
|
|
@ -48,6 +48,7 @@ func init() {
|
|||
}
|
||||
|
||||
// SimplePriceMatching implements a simple kline data driven matching engine for backtest
|
||||
//
|
||||
//go:generate callbackgen -type SimplePriceMatching
|
||||
type SimplePriceMatching struct {
|
||||
Symbol string
|
||||
|
|
|
@ -3,7 +3,6 @@ package backtest
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
@ -55,7 +54,7 @@ type SummaryReport struct {
|
|||
}
|
||||
|
||||
func ReadSummaryReport(filename string) (*SummaryReport, error) {
|
||||
o, err := ioutil.ReadFile(filename)
|
||||
o, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -247,7 +246,7 @@ func loadReportIndexLocked(indexFilePath string) (*ReportIndex, error) {
|
|||
if fileInfo, err := os.Stat(indexFilePath); err != nil {
|
||||
return nil, err
|
||||
} else if fileInfo.Size() != 0 {
|
||||
o, err := ioutil.ReadFile(indexFilePath)
|
||||
o, err := os.ReadFile(indexFilePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ func (b *ActiveOrderBook) BindStream(stream types.Stream) {
|
|||
stream.OnOrderUpdate(b.orderUpdateHandler)
|
||||
}
|
||||
|
||||
func (b *ActiveOrderBook) waitClear(
|
||||
func (b *ActiveOrderBook) waitOrderClear(
|
||||
ctx context.Context, order types.Order, waitTime, timeout time.Duration,
|
||||
) (bool, error) {
|
||||
if !b.orders.Exists(order.OrderID) {
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
@ -51,7 +50,7 @@ func generateRunFile(filepath string, config *Config, imports []string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
return ioutil.WriteFile(filepath, buf.Bytes(), 0644)
|
||||
return os.WriteFile(filepath, buf.Bytes(), 0644)
|
||||
}
|
||||
|
||||
// compilePackage generates the main.go file of the wrapper package
|
||||
|
@ -80,7 +79,7 @@ func Build(ctx context.Context, userConfig *Config, targetConfig BuildTargetConf
|
|||
buildDir = "build"
|
||||
}
|
||||
|
||||
packageDir, err := ioutil.TempDir(buildDir, "bbgow-") // with prefix bbgow
|
||||
packageDir, err := os.MkdirTemp(buildDir, "bbgow-") // with prefix bbgow
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
@ -496,7 +496,7 @@ func loadStash(config []byte) (Stash, error) {
|
|||
func LoadBuildConfig(configFile string) (*Config, error) {
|
||||
var config Config
|
||||
|
||||
content, err := ioutil.ReadFile(configFile)
|
||||
content, err := os.ReadFile(configFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -526,7 +526,7 @@ func LoadBuildConfig(configFile string) (*Config, error) {
|
|||
func Load(configFile string, loadStrategies bool) (*Config, error) {
|
||||
var config Config
|
||||
|
||||
content, err := ioutil.ReadFile(configFile)
|
||||
content, err := os.ReadFile(configFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ package bbgo
|
|||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -128,7 +128,7 @@ func TestLoadConfig(t *testing.T) {
|
|||
yamlText, err := config.YAML()
|
||||
assert.NoError(t, err)
|
||||
|
||||
yamlTextSource, err := ioutil.ReadFile("testdata/strategy.yaml")
|
||||
yamlTextSource, err := os.ReadFile("testdata/strategy.yaml")
|
||||
assert.NoError(t, err)
|
||||
|
||||
var sourceMap map[string]interface{}
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"image/png"
|
||||
"io/ioutil"
|
||||
stdlog "log"
|
||||
"math/rand"
|
||||
"os"
|
||||
|
@ -34,7 +33,7 @@ import (
|
|||
|
||||
func init() {
|
||||
// randomize pulling
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
}
|
||||
|
||||
var defaultSyncBufferPeriod = 30 * time.Minute
|
||||
|
@ -69,8 +68,6 @@ func RegisterStrategy(key string, s interface{}) {
|
|||
}
|
||||
}
|
||||
|
||||
var emptyTime time.Time
|
||||
|
||||
type SyncStatus int
|
||||
|
||||
const (
|
||||
|
@ -971,7 +968,7 @@ func writeOTPKeyAsQRCodePNG(key *otp.Key, imagePath string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(imagePath, buf.Bytes(), 0644); err != nil {
|
||||
if err := os.WriteFile(imagePath, buf.Bytes(), 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -5,8 +5,6 @@ import (
|
|||
"fmt"
|
||||
"path"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/dynamic"
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
|
@ -556,19 +554,6 @@ func getStrategySignature(strategy SingleExchangeStrategy) (string, error) {
|
|||
return signature, nil
|
||||
}
|
||||
|
||||
func parseFloatPercent(s string, bitSize int) (f float64, err error) {
|
||||
i := strings.Index(s, "%")
|
||||
if i < 0 {
|
||||
return strconv.ParseFloat(s, bitSize)
|
||||
}
|
||||
|
||||
f, err = strconv.ParseFloat(s[:i], bitSize)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return f / 100.0, nil
|
||||
}
|
||||
|
||||
func getStrategySignatures(exchangeStrategies map[string]SingleExchangeStrategy) []string {
|
||||
var strategies []string
|
||||
for signature := range exchangeStrategies {
|
||||
|
|
|
@ -3,7 +3,6 @@ package bbgo
|
|||
import (
|
||||
"context"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"go.uber.org/multierr"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/core"
|
||||
|
@ -14,8 +13,6 @@ import (
|
|||
// This order executor does not handle position and profit stats update
|
||||
type SimpleOrderExecutor struct {
|
||||
BaseOrderExecutor
|
||||
|
||||
logger log.FieldLogger
|
||||
}
|
||||
|
||||
func NewSimpleOrderExecutor(session *ExchangeSession) *SimpleOrderExecutor {
|
||||
|
|
|
@ -13,7 +13,6 @@ type PnLReporter interface {
|
|||
type baseReporter struct {
|
||||
notifier Notifier
|
||||
cron *cron.Cron
|
||||
environment *Environment
|
||||
}
|
||||
|
||||
type PnLReporterManager struct {
|
||||
|
|
|
@ -209,6 +209,9 @@ func (session *ExchangeSession) Init(ctx context.Context, environ *Environment)
|
|||
var err error
|
||||
if util.SetEnvVarBool("DISABLE_MARKETS_CACHE", &disableMarketsCache); disableMarketsCache {
|
||||
markets, err = session.Exchange.QueryMarkets(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
markets, err = cache.LoadExchangeMarketsWithCache(ctx, session.Exchange)
|
||||
if err != nil {
|
||||
|
|
5
pkg/cache/cache.go
vendored
5
pkg/cache/cache.go
vendored
|
@ -4,7 +4,6 @@ import (
|
|||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
|
@ -99,7 +98,7 @@ func WithCache(key string, obj interface{}, fetcher DataFetcher) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(cacheFile, out, 0666); err != nil {
|
||||
if err := os.WriteFile(cacheFile, out, 0666); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -113,7 +112,7 @@ func WithCache(key string, obj interface{}, fetcher DataFetcher) error {
|
|||
} else {
|
||||
log.Debugf("cache %s found", cacheFile)
|
||||
|
||||
data, err := ioutil.ReadFile(cacheFile)
|
||||
data, err := os.ReadFile(cacheFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -4,16 +4,16 @@ import (
|
|||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/optimizer"
|
||||
"github.com/fatih/color"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"gopkg.in/yaml.v3"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -69,7 +69,7 @@ var hoptimizeCmd = &cobra.Command{
|
|||
return err
|
||||
}
|
||||
|
||||
yamlBody, err := ioutil.ReadFile(configFile)
|
||||
yamlBody, err := os.ReadFile(configFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -37,11 +37,11 @@ var marginCmd = &cobra.Command{
|
|||
Short: "margin related history",
|
||||
SilenceUsage: true,
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
if err := cobraLoadDotenv(cmd, args); err != nil {
|
||||
if err := cobraLoadDotenv(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := cobraLoadConfig(cmd, args); err != nil {
|
||||
if err := cobraLoadConfig(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -60,7 +59,7 @@ var optimizeCmd = &cobra.Command{
|
|||
return err
|
||||
}
|
||||
|
||||
yamlBody, err := ioutil.ReadFile(configFile)
|
||||
yamlBody, err := os.ReadFile(configFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -22,8 +22,6 @@ import (
|
|||
"github.com/c9s/bbgo/pkg/util"
|
||||
|
||||
_ "time/tzdata"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
)
|
||||
|
||||
var cpuProfileFile *os.File
|
||||
|
@ -38,7 +36,7 @@ var RootCmd = &cobra.Command{
|
|||
SilenceUsage: true,
|
||||
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
if err := cobraLoadDotenv(cmd, args); err != nil {
|
||||
if err := cobraLoadDotenv(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -101,7 +99,7 @@ var RootCmd = &cobra.Command{
|
|||
}
|
||||
}
|
||||
|
||||
return cobraLoadConfig(cmd, args)
|
||||
return cobraLoadConfig(cmd)
|
||||
},
|
||||
PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
|
||||
pprof.StopCPUProfile()
|
||||
|
@ -116,7 +114,7 @@ var RootCmd = &cobra.Command{
|
|||
},
|
||||
}
|
||||
|
||||
func cobraLoadDotenv(cmd *cobra.Command, args []string) error {
|
||||
func cobraLoadDotenv(cmd *cobra.Command) error {
|
||||
disableDotEnv, err := cmd.Flags().GetBool("no-dotenv")
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -137,7 +135,7 @@ func cobraLoadDotenv(cmd *cobra.Command, args []string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func cobraLoadConfig(cmd *cobra.Command, args []string) error {
|
||||
func cobraLoadConfig(cmd *cobra.Command) error {
|
||||
configFile, err := cmd.Flags().GetString("config")
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get the config flag")
|
||||
|
|
|
@ -2,7 +2,6 @@ package cmd
|
|||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
@ -308,7 +307,7 @@ func runWrapperBinary(ctx context.Context, cmd *cobra.Command, userConfig *bbgo.
|
|||
|
||||
// buildAndRun builds the package natively and run the binary with the given args
|
||||
func buildAndRun(ctx context.Context, userConfig *bbgo.Config, args ...string) (*exec.Cmd, error) {
|
||||
packageDir, err := ioutil.TempDir("build", "bbgow")
|
||||
packageDir, err := os.MkdirTemp("build", "bbgow")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func cobraInitRequired(required []string) func(cmd *cobra.Command, args []string) error {
|
||||
|
|
|
@ -867,7 +867,7 @@ type MarkPriceUpdateEvent struct {
|
|||
type ContinuousKLineEvent struct {
|
||||
EventBase
|
||||
Symbol string `json:"ps"`
|
||||
ct string `json:"ct"`
|
||||
CT string `json:"ct"`
|
||||
KLine KLine `json:"k,omitempty"`
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ package optimizer
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
|
@ -57,7 +57,7 @@ var defaultLocalExecutorConfig = &LocalExecutorConfig{
|
|||
}
|
||||
|
||||
func LoadConfig(yamlConfigFileName string) (*Config, error) {
|
||||
configYaml, err := ioutil.ReadFile(yamlConfigFileName)
|
||||
configYaml, err := os.ReadFile(yamlConfigFileName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -3,12 +3,10 @@ package server
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
|
@ -525,7 +523,7 @@ func (s *Server) setupSaveConfig(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(filename, out, 0666); err != nil {
|
||||
if err := os.WriteFile(filename, out, 0666); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
@ -533,7 +531,7 @@ func (s *Server) setupSaveConfig(c *gin.Context) {
|
|||
c.JSON(http.StatusOK, gin.H{"success": true})
|
||||
}
|
||||
|
||||
var pageRoutePattern = regexp.MustCompile("/[a-z]+$")
|
||||
// var pageRoutePattern = regexp.MustCompile("/[a-z]+$")
|
||||
|
||||
func moveFileToBackup(filename string) error {
|
||||
stat, err := os.Stat(filename)
|
||||
|
|
|
@ -2,7 +2,6 @@ package service
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
@ -49,7 +48,7 @@ func (store JsonStore) Load(val interface{}) error {
|
|||
return ErrPersistenceNotExists
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadFile(p)
|
||||
data, err := os.ReadFile(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -74,5 +73,5 @@ func (store JsonStore) Save(val interface{}) error {
|
|||
}
|
||||
|
||||
p := filepath.Join(store.Directory, store.ID) + ".json"
|
||||
return ioutil.WriteFile(p, data, 0666)
|
||||
return os.WriteFile(p, data, 0666)
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
@ -108,7 +107,7 @@ func NewTestDataService(t *TestData) *TestDataService {
|
|||
}
|
||||
|
||||
func readSpec(fileName string) (*TestData, error) {
|
||||
content, err := ioutil.ReadFile(fileName)
|
||||
content, err := os.ReadFile(fileName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ package util
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
|
@ -17,7 +17,7 @@ type Response struct {
|
|||
|
||||
// NewResponse is a wrapper of the http.Response instance, it reads the response body and close the file.
|
||||
func NewResponse(r *http.Response) (response *Response, err error) {
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ package util
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
|
@ -14,7 +14,7 @@ func TestResponse_DecodeJSON(t *testing.T) {
|
|||
Name string `json:"name"`
|
||||
}
|
||||
json := `{"name":"Test Name","a":"a"}`
|
||||
reader := ioutil.NopCloser(bytes.NewReader([]byte(json)))
|
||||
reader := io.NopCloser(bytes.NewReader([]byte(json)))
|
||||
resp, err := NewResponse(&http.Response{
|
||||
StatusCode: 200,
|
||||
Body: reader,
|
||||
|
|
|
@ -3,7 +3,6 @@ package util
|
|||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
|
||||
|
@ -13,7 +12,7 @@ func WriteJsonFile(p string, obj interface{}) error {
|
|||
return err
|
||||
}
|
||||
|
||||
return ioutil.WriteFile(p, out, 0644)
|
||||
return os.WriteFile(p, out, 0644)
|
||||
}
|
||||
|
||||
func ReadJsonFile(file string, obj interface{}) error {
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
@ -119,14 +118,14 @@ func Embed(file string, dirs ...string) error {
|
|||
|
||||
log.Printf("packing %s...", path)
|
||||
|
||||
b, err := ioutil.ReadFile(path)
|
||||
b, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
path = filepath.ToSlash(path)
|
||||
fmt.Fprintf(w, ` assets[%q] = []byte{`, strings.TrimPrefix(path, dir))
|
||||
fmt.Fprintf(w, formatBytes(b))
|
||||
fmt.Fprint(w, formatBytes(b))
|
||||
fmt.Fprintln(w, `}`)
|
||||
return nil
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue
Block a user