Combined all commands in single file
This commit is contained in:
parent
f6e8038cdc
commit
13b5f86bdd
@ -1,63 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"math/rand"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
func commandCatch(p *PokedexConfig, a *string) error {
|
|
||||||
if *a == "" {
|
|
||||||
return fmt.Errorf("you need to specify a Pokemon to catch")
|
|
||||||
}
|
|
||||||
var pokemonName string
|
|
||||||
var baseUrl string
|
|
||||||
for _, encounter := range p.LocalPokemons.PokemonEncounters {
|
|
||||||
if encounter.PokemonSummary.Name == *a {
|
|
||||||
pokemonName = *a
|
|
||||||
baseUrl = encounter.PokemonSummary.DataUrl
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if pokemonName == "" {
|
|
||||||
baseUrl = "https://pokeapi.co/api/v2/pokemon/" + *a
|
|
||||||
}
|
|
||||||
// if pokemonName != *a {
|
|
||||||
// fmt.Println("this pokemon is not present in the current area")
|
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
|
|
||||||
body, exists := p.Cache.Get(baseUrl)
|
|
||||||
if !exists {
|
|
||||||
client := http.Client{}
|
|
||||||
|
|
||||||
resp, err := client.Get(baseUrl)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("could not make request to Pokedex API! Err: %w", err)
|
|
||||||
}
|
|
||||||
body, err = io.ReadAll(resp.Body)
|
|
||||||
defer resp.Body.Close()
|
|
||||||
if resp.StatusCode > 299 {
|
|
||||||
return fmt.Errorf("request returned non-200 code! Code: %v Body: %v", resp.StatusCode, body)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("could not read request body! Err: %w", err)
|
|
||||||
}
|
|
||||||
p.Cache.Add(baseUrl, body)
|
|
||||||
}
|
|
||||||
var pokemon PokemonDetails
|
|
||||||
if err := json.Unmarshal(body, &pokemon); err != nil {
|
|
||||||
return fmt.Errorf("could not unmarshal Pokemon data! err: %w", err)
|
|
||||||
}
|
|
||||||
fmt.Printf("Throwing a Pokeball at %s...\n", *a)
|
|
||||||
catchSuccess := rand.Intn(pokemon.BaseExperience)
|
|
||||||
if 2*catchSuccess >= pokemon.BaseExperience {
|
|
||||||
fmt.Printf("%s was caught!\n", pokemon.Name)
|
|
||||||
p.CaughtPokemon = append(p.CaughtPokemon, pokemon)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
fmt.Printf("%s escaped!\n", *a)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func commandExit(p *PokedexConfig, a *string) error {
|
|
||||||
fmt.Println("Closing the Pokedex... Goodbye!")
|
|
||||||
os.Exit(0)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
func commandExplore(p *PokedexConfig, a *string) error {
|
|
||||||
if *a == "" {
|
|
||||||
return fmt.Errorf("you need to specify an area to explore")
|
|
||||||
}
|
|
||||||
baseUrl := "https://pokeapi.co/api/v2/location-area/" + *a + "/"
|
|
||||||
body, exists := p.Cache.Get(baseUrl)
|
|
||||||
if !exists {
|
|
||||||
client := http.Client{}
|
|
||||||
|
|
||||||
resp, err := client.Get(baseUrl)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("could not make request to Pokedex API! Err: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
body, err = io.ReadAll(resp.Body)
|
|
||||||
defer resp.Body.Close()
|
|
||||||
if resp.StatusCode > 299 {
|
|
||||||
return fmt.Errorf("request returned non-200 code! Code: %v Body: %v", resp.StatusCode, body)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("could not read request body! Err: %w", err)
|
|
||||||
}
|
|
||||||
p.Cache.Add(baseUrl, body)
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal(body, &p.LocalPokemons); err != nil {
|
|
||||||
return fmt.Errorf("could not unmarshal response! Err: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, pokemon := range p.LocalPokemons.PokemonEncounters {
|
|
||||||
fmt.Println(pokemon.PokemonSummary.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
func commandHelp(p *PokedexConfig, a *string) error {
|
|
||||||
fmt.Print("Pokedex CLI - available commands:\n\n")
|
|
||||||
for _, v := range getCommands() {
|
|
||||||
fmt.Printf("%s %s\n", v.name, v.description)
|
|
||||||
}
|
|
||||||
fmt.Println()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@ -1,45 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"gopkg.in/yaml.v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
type PokemonInspectOutput struct {
|
|
||||||
Name string
|
|
||||||
Height int
|
|
||||||
Weight int
|
|
||||||
Stats map[string]int
|
|
||||||
Types []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func commandInspect(p *PokedexConfig, a *string) error {
|
|
||||||
found := false
|
|
||||||
for _, pokemon := range p.CaughtPokemon {
|
|
||||||
if pokemon.Name == *a {
|
|
||||||
found = true
|
|
||||||
stats := map[string]int{}
|
|
||||||
types := []string{}
|
|
||||||
for _, pokeStat := range pokemon.PokeStats {
|
|
||||||
stats[pokeStat.PokeStat.Name] = pokeStat.BaseStat
|
|
||||||
}
|
|
||||||
for _, pokeType := range pokemon.PokeTypes {
|
|
||||||
types = append(types, pokeType.PokeType.Name)
|
|
||||||
}
|
|
||||||
pokemonInspectOutput := PokemonInspectOutput{
|
|
||||||
Name: pokemon.Name,
|
|
||||||
Height: pokemon.Height,
|
|
||||||
Weight: pokemon.Weight,
|
|
||||||
Stats: stats,
|
|
||||||
Types: types,
|
|
||||||
}
|
|
||||||
data, _ := yaml.Marshal(pokemonInspectOutput)
|
|
||||||
fmt.Println(string(data))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !found {
|
|
||||||
fmt.Println("you have not caught that pokemon")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@ -1,48 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
func commandMap(p *PokedexConfig, a *string) error {
|
|
||||||
var baseUrl string
|
|
||||||
if p.LocationData.Next == nil {
|
|
||||||
baseUrl = "https://pokeapi.co/api/v2/location-area/"
|
|
||||||
} else {
|
|
||||||
baseUrl = *p.LocationData.Next
|
|
||||||
}
|
|
||||||
|
|
||||||
var body []byte
|
|
||||||
// Check if respones is available in cache
|
|
||||||
if resp, exists := p.Cache.Get(baseUrl); exists {
|
|
||||||
body = resp
|
|
||||||
} else {
|
|
||||||
client := &http.Client{}
|
|
||||||
|
|
||||||
resp, err := client.Get(baseUrl)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("could not make request to Pokedex API! Err: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
body, err = io.ReadAll(resp.Body)
|
|
||||||
defer resp.Body.Close()
|
|
||||||
if resp.StatusCode > 299 {
|
|
||||||
return fmt.Errorf("request returned non-200 code! Code: %v Body: %v", resp.StatusCode, body)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("could not read request body! Err: %w", err)
|
|
||||||
}
|
|
||||||
p.Cache.Add(baseUrl, body)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := json.Unmarshal(body, &p.LocationData); err != nil {
|
|
||||||
return fmt.Errorf("could not unmarshal response! Err: %w", err)
|
|
||||||
}
|
|
||||||
for _, location := range p.LocationData.Locations {
|
|
||||||
fmt.Println(location["name"])
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@ -1,47 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
func commandMapb(p *PokedexConfig, a *string) error {
|
|
||||||
var baseUrl string
|
|
||||||
if p.LocationData.Previous == nil {
|
|
||||||
fmt.Println("you're on the first page")
|
|
||||||
return nil
|
|
||||||
} else {
|
|
||||||
baseUrl = *p.LocationData.Previous
|
|
||||||
}
|
|
||||||
var body []byte
|
|
||||||
if resp, exists := p.Cache.Get(baseUrl); exists {
|
|
||||||
body = resp
|
|
||||||
} else {
|
|
||||||
client := &http.Client{}
|
|
||||||
|
|
||||||
resp, err := client.Get(baseUrl)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("could not make request to Pokedex API! Err: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
body, err = io.ReadAll(resp.Body)
|
|
||||||
defer resp.Body.Close()
|
|
||||||
if resp.StatusCode > 299 {
|
|
||||||
return fmt.Errorf("request returned non-200 code! Code: %v Body: %v", resp.StatusCode, body)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("could not read request body! Err: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
p.Cache.Add(baseUrl, body)
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal(body, &p.LocationData); err != nil {
|
|
||||||
return fmt.Errorf("could not unmarshal response! Err: %w", err)
|
|
||||||
}
|
|
||||||
for _, location := range p.LocationData.Locations {
|
|
||||||
fmt.Println(location["name"])
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
func commandPokedex(p *PokedexConfig, a *string) error {
|
|
||||||
if len(p.CaughtPokemon) == 0 {
|
|
||||||
fmt.Println("Your Pokedex is empty.")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
fmt.Println("Your Pokedex:")
|
|
||||||
for _, pokemon := range p.CaughtPokemon {
|
|
||||||
fmt.Println(" - ", pokemon.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
244
commands.go
Normal file
244
commands.go
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"math/rand"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PokemonInspectOutput struct {
|
||||||
|
Name string
|
||||||
|
Height int
|
||||||
|
Weight int
|
||||||
|
Stats map[string]int
|
||||||
|
Types []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func commandHelp(p *PokedexConfig, a *string) error {
|
||||||
|
fmt.Print("Pokedex CLI - available commands:\n\n")
|
||||||
|
for _, v := range getCommands() {
|
||||||
|
fmt.Printf("%s %s\n", v.name, v.description)
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func commandExit(p *PokedexConfig, a *string) error {
|
||||||
|
fmt.Println("Closing the Pokedex... Goodbye!")
|
||||||
|
os.Exit(0)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func commandMap(p *PokedexConfig, a *string) error {
|
||||||
|
var baseUrl string
|
||||||
|
if p.LocationData.Next == nil {
|
||||||
|
baseUrl = "https://pokeapi.co/api/v2/location-area/"
|
||||||
|
} else {
|
||||||
|
baseUrl = *p.LocationData.Next
|
||||||
|
}
|
||||||
|
|
||||||
|
var body []byte
|
||||||
|
|
||||||
|
if resp, exists := p.Cache.Get(baseUrl); exists {
|
||||||
|
body = resp
|
||||||
|
} else {
|
||||||
|
client := &http.Client{}
|
||||||
|
|
||||||
|
resp, err := client.Get(baseUrl)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not make request to Pokedex API! Err: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err = io.ReadAll(resp.Body)
|
||||||
|
defer resp.Body.Close()
|
||||||
|
if resp.StatusCode > 299 {
|
||||||
|
return fmt.Errorf("request returned non-200 code! Code: %v Body: %v", resp.StatusCode, body)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not read request body! Err: %w", err)
|
||||||
|
}
|
||||||
|
p.Cache.Add(baseUrl, body)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(body, &p.LocationData); err != nil {
|
||||||
|
return fmt.Errorf("could not unmarshal response! Err: %w", err)
|
||||||
|
}
|
||||||
|
for _, location := range p.LocationData.Locations {
|
||||||
|
fmt.Println(location["name"])
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func commandMapb(p *PokedexConfig, a *string) error {
|
||||||
|
var baseUrl string
|
||||||
|
if p.LocationData.Previous == nil {
|
||||||
|
fmt.Println("you're on the first page")
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
baseUrl = *p.LocationData.Previous
|
||||||
|
}
|
||||||
|
var body []byte
|
||||||
|
if resp, exists := p.Cache.Get(baseUrl); exists {
|
||||||
|
body = resp
|
||||||
|
} else {
|
||||||
|
client := &http.Client{}
|
||||||
|
|
||||||
|
resp, err := client.Get(baseUrl)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not make request to Pokedex API! Err: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err = io.ReadAll(resp.Body)
|
||||||
|
defer resp.Body.Close()
|
||||||
|
if resp.StatusCode > 299 {
|
||||||
|
return fmt.Errorf("request returned non-200 code! Code: %v Body: %v", resp.StatusCode, body)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not read request body! Err: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Cache.Add(baseUrl, body)
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(body, &p.LocationData); err != nil {
|
||||||
|
return fmt.Errorf("could not unmarshal response! Err: %w", err)
|
||||||
|
}
|
||||||
|
for _, location := range p.LocationData.Locations {
|
||||||
|
fmt.Println(location["name"])
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func commandExplore(p *PokedexConfig, a *string) error {
|
||||||
|
if *a == "" {
|
||||||
|
return fmt.Errorf("you need to specify an area to explore")
|
||||||
|
}
|
||||||
|
baseUrl := "https://pokeapi.co/api/v2/location-area/" + *a + "/"
|
||||||
|
body, exists := p.Cache.Get(baseUrl)
|
||||||
|
if !exists {
|
||||||
|
client := http.Client{}
|
||||||
|
|
||||||
|
resp, err := client.Get(baseUrl)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not make request to Pokedex API! Err: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err = io.ReadAll(resp.Body)
|
||||||
|
defer resp.Body.Close()
|
||||||
|
if resp.StatusCode > 299 {
|
||||||
|
return fmt.Errorf("request returned non-200 code! Code: %v Body: %v", resp.StatusCode, body)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not read request body! Err: %w", err)
|
||||||
|
}
|
||||||
|
p.Cache.Add(baseUrl, body)
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(body, &p.LocalPokemons); err != nil {
|
||||||
|
return fmt.Errorf("could not unmarshal response! Err: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pokemon := range p.LocalPokemons.PokemonEncounters {
|
||||||
|
fmt.Println(pokemon.PokemonSummary.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func commandCatch(p *PokedexConfig, a *string) error {
|
||||||
|
if *a == "" {
|
||||||
|
return fmt.Errorf("you need to specify a Pokemon to catch")
|
||||||
|
}
|
||||||
|
var pokemonName string
|
||||||
|
var baseUrl string
|
||||||
|
for _, encounter := range p.LocalPokemons.PokemonEncounters {
|
||||||
|
if encounter.PokemonSummary.Name == *a {
|
||||||
|
pokemonName = *a
|
||||||
|
baseUrl = encounter.PokemonSummary.DataUrl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if pokemonName != *a {
|
||||||
|
fmt.Println("this pokemon is not present in the current area")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
body, exists := p.Cache.Get(baseUrl)
|
||||||
|
if !exists {
|
||||||
|
client := http.Client{}
|
||||||
|
|
||||||
|
resp, err := client.Get(baseUrl)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not make request to Pokedex API! Err: %w", err)
|
||||||
|
}
|
||||||
|
body, err = io.ReadAll(resp.Body)
|
||||||
|
defer resp.Body.Close()
|
||||||
|
if resp.StatusCode > 299 {
|
||||||
|
return fmt.Errorf("request returned non-200 code! Code: %v Body: %v", resp.StatusCode, body)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not read request body! Err: %w", err)
|
||||||
|
}
|
||||||
|
p.Cache.Add(baseUrl, body)
|
||||||
|
}
|
||||||
|
var pokemon PokemonDetails
|
||||||
|
if err := json.Unmarshal(body, &pokemon); err != nil {
|
||||||
|
return fmt.Errorf("could not unmarshal Pokemon data! err: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Throwing a Pokeball at %s...\n", *a)
|
||||||
|
catchSuccess := rand.Intn(pokemon.BaseExperience)
|
||||||
|
if 2*catchSuccess >= pokemon.BaseExperience {
|
||||||
|
fmt.Printf("%s was caught!\n", pokemon.Name)
|
||||||
|
p.CaughtPokemon = append(p.CaughtPokemon, pokemon)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
fmt.Printf("%s escaped!\n", *a)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func commandPokedex(p *PokedexConfig, a *string) error {
|
||||||
|
if len(p.CaughtPokemon) == 0 {
|
||||||
|
fmt.Println("Your Pokedex is empty.")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
fmt.Println("Your Pokedex:")
|
||||||
|
for _, pokemon := range p.CaughtPokemon {
|
||||||
|
fmt.Println(" - ", pokemon.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func commandInspect(p *PokedexConfig, a *string) error {
|
||||||
|
found := false
|
||||||
|
for _, pokemon := range p.CaughtPokemon {
|
||||||
|
if pokemon.Name == *a {
|
||||||
|
found = true
|
||||||
|
stats := map[string]int{}
|
||||||
|
types := []string{}
|
||||||
|
for _, pokeStat := range pokemon.PokeStats {
|
||||||
|
stats[pokeStat.PokeStat.Name] = pokeStat.BaseStat
|
||||||
|
}
|
||||||
|
for _, pokeType := range pokemon.PokeTypes {
|
||||||
|
types = append(types, pokeType.PokeType.Name)
|
||||||
|
}
|
||||||
|
pokemonInspectOutput := PokemonInspectOutput{
|
||||||
|
Name: pokemon.Name,
|
||||||
|
Height: pokemon.Height,
|
||||||
|
Weight: pokemon.Weight,
|
||||||
|
Stats: stats,
|
||||||
|
Types: types,
|
||||||
|
}
|
||||||
|
data, _ := yaml.Marshal(pokemonInspectOutput)
|
||||||
|
fmt.Println(string(data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
fmt.Println("you have not caught that pokemon")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user