package shrty import ( "fmt" "crypto/sha256" "time" "encoding/json" ) type Data struct { URL string `json:"url"` URLFetched string `json:"url_fetched"` CanonicalURL string `json:"canonical_url"` OriginalURL string `json:"original_url"` Domain string `json:"domain"` Hash string `json:"hash"` Token string `json:"token"` Meta `json:"meta"` FavIconLink string `json:"favicon_url"` HTTPStatusCode string `json:"http_code"` Category string `json:"category"` Created string `json:"created_at"` Clicks int64 `json:"clicks"` } type Meta struct{ Title string `json:"title"meta:"og:title"` Image string `json:"image"meta:"og:image"` Description string `json:"description"meta:"og:description"` Type string `json:"type"meta:"og:type"` } func (s *Store) Short(URL string, value *string) error { d := &Data{ URL: URL, } err := CheckURL(d) if err != nil { return err } // Create a sha256 Hash from the URL d.Hash = fmt.Sprintf("%x", sha256.Sum256([]byte(d.OriginalURL))) // Check if the URL already in the Storage if ok := s.Exist(d); ok { *value = d.Token return nil } // Iterate to the length of the hash to get the shortest output for hashShortestLen := 1; hashShortestLen <= 32; hashShortestLen++ { // Test if the Token not exist and return the new generated token if _, ok := s.Token[d.Hash[:hashShortestLen]]; !ok { d.Token = d.Hash[:hashShortestLen] d.Created = time.Now().String() s.Token[d.Token] = d s.Url[d.Hash] = d.Token *value = d.Token s.Save() return nil } } return ErrCreateToken } // URL already Exist in the func (s *Store) Exist(d *Data) bool { if val, ok := s.Url[d.Hash]; ok { d = s.Token[val] return true } return false } // Returns the URL for the given token func (s *Store) Redirect(token string) (string, bool) { if shrt, ok := s.Token[token]; ok { s.Token[token].Clicks += 1 s.Save() return shrt.OriginalURL, true } return "", false } // Get Data for the given Token func (s *Store) Get(token string, value *Data) bool { if data, ok := s.Token[token]; ok { *value = *data return true } return false } // Get all entries func (s *Store) GetAll() string { b, err := json.Marshal(&s) if err != nil { return "" } return string(b) }