photoprism/internal/maps/location.go

203 lines
3.9 KiB
Go
Raw Normal View History

package maps
import (
"errors"
"strings"
"github.com/photoprism/photoprism/internal/maps/osm"
"github.com/photoprism/photoprism/internal/maps/places"
"github.com/photoprism/photoprism/pkg/s2"
)
/* TODO
(SELECT pl.loc_label as album_name, pl.loc_country, YEAR(ph.taken_at) as taken_year, round(count(ph.id)) as photo_count FROM photos ph
JOIN places pl ON ph.place_id = pl.id AND pl.id <> 1
GROUP BY album_name, taken_year HAVING photo_count > 5) UNION (
SELECT c.country_name AS album_name, pl.loc_country, YEAR(ph.taken_at) as taken_year, round(count(ph.id)) as photo_count FROM photos ph
JOIN places pl ON ph.place_id = pl.id AND pl.id <> 1
JOIN countries c ON c.id = pl.loc_country
GROUP BY album_name, taken_year
HAVING photo_count > 10)
ORDER BY loc_country, album_name, taken_year;
*/
// Photo location
type Location struct {
ID string
LocName string
LocCategory string
LocLabel string
LocCity string
LocState string
LocCountry string
LocSource string
LocKeywords []string
}
type LocationSource interface {
CellID() string
CountryCode() string
Category() string
Name() string
City() string
State() string
Source() string
Keywords() []string
}
func NewLocation(id, name, category, label, city, state, country, source string, keywords []string) *Location {
result := &Location{
ID: id,
LocName: name,
LocCategory: category,
LocLabel: label,
LocCity: city,
LocState: state,
LocCountry: country,
LocSource: source,
LocKeywords: keywords,
}
return result
}
func (l *Location) QueryApi(api string) error {
switch api {
case "osm":
return l.QueryOSM()
case "places":
return l.QueryPlaces()
}
return errors.New("maps: reverse lookup disabled")
}
func (l *Location) QueryPlaces() error {
s, err := places.FindLocation(l.ID)
if err != nil {
return err
}
l.LocSource = s.Source()
l.LocName = s.Name()
l.LocCity = s.City()
l.LocState = s.State()
l.LocCountry = s.CountryCode()
l.LocCategory = s.Category()
l.LocLabel = s.Label()
l.LocKeywords = s.Keywords()
return nil
}
func (l *Location) QueryOSM() error {
s, err := osm.FindLocation(l.ID)
if err != nil {
return err
}
return l.Assign(s)
}
func (l *Location) Assign(s LocationSource) error {
l.LocSource = s.Source()
l.ID = s.CellID()
if l.Unknown() {
l.LocCategory = "unknown"
return errors.New("maps: unknown location")
}
l.LocName = s.Name()
l.LocCity = s.City()
l.LocState = s.State()
l.LocCountry = s.CountryCode()
l.LocCategory = s.Category()
l.LocLabel = l.label()
l.LocKeywords = s.Keywords()
return nil
}
func (l *Location) Unknown() bool {
return l.ID == ""
}
func (l *Location) label() string {
if l.Unknown() {
return "Unknown"
}
var countryName = l.CountryName()
var loc []string
shortCountry := len([]rune(countryName)) <= 20
if l.LocCity != "" {
loc = append(loc, l.LocCity)
}
if shortCountry && l.LocState != "" && l.LocCity != l.LocState {
loc = append(loc, l.LocState)
}
if countryName != "" {
loc = append(loc, countryName)
}
return strings.Join(loc[:], ", ")
}
func (l Location) S2Token() string {
return l.ID
}
func (l Location) PrefixedToken() string {
return s2.Prefix(l.ID)
}
func (l Location) Name() string {
return l.LocName
}
func (l Location) Category() string {
return l.LocCategory
}
func (l Location) Label() string {
return l.LocLabel
}
func (l Location) City() string {
return l.LocCity
}
func (l Location) State() string {
return l.LocState
}
func (l Location) CountryCode() string {
return l.LocCountry
}
func (l Location) CountryName() string {
return CountryNames[l.LocCountry]
}
func (l Location) Source() string {
return l.LocSource
}
func (l Location) Keywords() []string {
return l.LocKeywords
}
func (l Location) KeywordString() string {
return strings.Join(l.LocKeywords, ", ")
}