2022-03-18 14:48:59 +00:00
|
|
|
package saltyim
|
|
|
|
|
|
|
|
import (
|
2022-03-18 22:50:04 +00:00
|
|
|
"crypto/sha256"
|
2022-03-18 14:48:59 +00:00
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"net/http"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
)
|
|
|
|
|
2022-03-18 15:13:31 +00:00
|
|
|
// Addr represents a Salty IM User's Address
|
|
|
|
type Addr struct {
|
2022-03-18 14:48:59 +00:00
|
|
|
User string
|
|
|
|
Domain string
|
|
|
|
}
|
|
|
|
|
2022-03-18 22:50:04 +00:00
|
|
|
func (a Addr) String() string {
|
|
|
|
return fmt.Sprint(a.User, "@", a.Domain)
|
|
|
|
}
|
2022-03-19 01:24:07 +00:00
|
|
|
|
|
|
|
// Formatted returns a formatted user used in the Salty Message Format
|
|
|
|
// <timestamp\t(<user>) <message>\n
|
2022-03-18 22:50:04 +00:00
|
|
|
func (a Addr) Formatted() string {
|
|
|
|
return fmt.Sprintf("(%s)", a)
|
|
|
|
}
|
|
|
|
|
2022-03-18 15:13:31 +00:00
|
|
|
// URI returns the Well-Known URI for this Addr
|
|
|
|
func (a Addr) URI() string {
|
|
|
|
return fmt.Sprintf("https://%s/.well-known/salty/%s.json", a.Domain, a.User)
|
2022-03-18 14:48:59 +00:00
|
|
|
}
|
|
|
|
|
2022-03-18 22:50:04 +00:00
|
|
|
// HashURI returns the Well-Known HashURI for this Addr
|
2022-03-19 01:24:07 +00:00
|
|
|
func (a Addr) HashURI() string {
|
|
|
|
return fmt.Sprintf("https://%s/.well-known/salty/%x.json", a.Domain, sha256.Sum256([]byte(a.String())))
|
2022-03-18 22:50:04 +00:00
|
|
|
}
|
|
|
|
|
2022-03-18 15:13:31 +00:00
|
|
|
// ParseAddr parsers a Salty Address for a user into it's user and domain
|
|
|
|
// parts and returns an Addr object with the User and Domain and a method
|
|
|
|
// for returning the expected User's Well-Known URI
|
|
|
|
func ParseAddr(addr string) (Addr, error) {
|
|
|
|
parts := strings.Split(addr, "@")
|
2022-03-18 14:48:59 +00:00
|
|
|
if len(parts) != 2 {
|
2022-03-18 15:13:31 +00:00
|
|
|
return Addr{}, fmt.Errorf("error parsing addr %q, expected nick@domain", addr)
|
2022-03-18 14:48:59 +00:00
|
|
|
}
|
|
|
|
|
2022-03-18 15:13:31 +00:00
|
|
|
return Addr{parts[0], parts[1]}, nil
|
2022-03-18 14:48:59 +00:00
|
|
|
}
|
|
|
|
|
2022-03-18 15:13:31 +00:00
|
|
|
// Lookup looks up a Salty Address for a User by parsing the user's domain and
|
|
|
|
// making a request to the user's Well-Known URI expected to be located at
|
2022-03-18 14:48:59 +00:00
|
|
|
// https://domain/.well-known/salty/<user>.json
|
2022-03-18 15:13:31 +00:00
|
|
|
func Lookup(addr string) (Config, error) {
|
|
|
|
a, err := ParseAddr(addr)
|
2022-03-18 14:48:59 +00:00
|
|
|
if err != nil {
|
2022-03-18 15:13:31 +00:00
|
|
|
log.WithError(err).Errorf("error parsing addr %q", addr)
|
2022-03-18 22:50:04 +00:00
|
|
|
return Config{}, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Attempt using hash
|
2022-03-19 01:24:07 +00:00
|
|
|
res, err := Request(http.MethodGet, a.HashURI(), nil, nil)
|
2022-03-18 22:50:04 +00:00
|
|
|
if err != nil {
|
|
|
|
// Fallback to plain user nick
|
2022-03-19 01:24:07 +00:00
|
|
|
res, err = Request(http.MethodGet, a.URI(), nil, nil)
|
2022-03-18 14:48:59 +00:00
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
log.WithError(err).Error("error requesting well-known uri")
|
2022-03-18 22:50:04 +00:00
|
|
|
return Config{}, err
|
2022-03-18 14:48:59 +00:00
|
|
|
}
|
|
|
|
|
2022-03-19 01:24:07 +00:00
|
|
|
data, err := ioutil.ReadAll(res.Body)
|
|
|
|
if err != nil {
|
|
|
|
log.WithError(err).Errorf("error reading well-known config")
|
|
|
|
return Config{}, err
|
|
|
|
}
|
|
|
|
|
2022-03-18 22:50:04 +00:00
|
|
|
var config Config
|
|
|
|
if err := json.Unmarshal(data, &config); err != nil {
|
|
|
|
log.WithError(err).Error("error parsing well-known config")
|
2022-03-19 04:12:33 +00:00
|
|
|
return Config{}, err
|
2022-03-18 14:48:59 +00:00
|
|
|
}
|
|
|
|
|
2022-03-18 22:50:04 +00:00
|
|
|
return config, err
|
|
|
|
}
|