245 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			245 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| 
								 | 
							
								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
							 | 
						||
| 
								 | 
							
								}
							 |