Country Flags and Genders for the chat room
This commit is contained in:
parent
22d485156f
commit
0c5db949aa
|
@ -10,6 +10,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.nonshy.com/nonshy/website/pkg/config"
|
"code.nonshy.com/nonshy/website/pkg/config"
|
||||||
|
"code.nonshy.com/nonshy/website/pkg/geoip"
|
||||||
"code.nonshy.com/nonshy/website/pkg/log"
|
"code.nonshy.com/nonshy/website/pkg/log"
|
||||||
"code.nonshy.com/nonshy/website/pkg/models"
|
"code.nonshy.com/nonshy/website/pkg/models"
|
||||||
"code.nonshy.com/nonshy/website/pkg/photo"
|
"code.nonshy.com/nonshy/website/pkg/photo"
|
||||||
|
@ -22,16 +23,32 @@ import (
|
||||||
// JWT claims.
|
// JWT claims.
|
||||||
type Claims struct {
|
type Claims struct {
|
||||||
// Custom claims.
|
// Custom claims.
|
||||||
IsAdmin bool `json:"op"`
|
IsAdmin bool `json:"op,omitempty"`
|
||||||
Avatar string `json:"img"`
|
Avatar string `json:"img,omitempty"`
|
||||||
ProfileURL string `json:"url"`
|
ProfileURL string `json:"url,omitempty"`
|
||||||
Nickname string `json:"nick"`
|
Nickname string `json:"nick,omitempty"`
|
||||||
|
Emoji string `json:"emoji,omitempty"`
|
||||||
|
Gender string `json:"gender,omitempty"`
|
||||||
|
|
||||||
// Standard claims. Notes:
|
// Standard claims. Notes:
|
||||||
// subject = username
|
// subject = username
|
||||||
jwt.RegisteredClaims
|
jwt.RegisteredClaims
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gender returns the BareRTC gender string for the user's gender selection.
|
||||||
|
func Gender(u *models.User) string {
|
||||||
|
switch u.GetProfileField("gender") {
|
||||||
|
case "Man", "Trans (FTM)":
|
||||||
|
return "m"
|
||||||
|
case "Woman", "Trans (MTF)":
|
||||||
|
return "f"
|
||||||
|
case "Non-binary", "Trans", "Other":
|
||||||
|
return "o"
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Landing page for chat rooms.
|
// Landing page for chat rooms.
|
||||||
func Landing() http.HandlerFunc {
|
func Landing() http.HandlerFunc {
|
||||||
tmpl := templates.Must("chat.html")
|
tmpl := templates.Must("chat.html")
|
||||||
|
@ -80,12 +97,23 @@ func Landing() http.HandlerFunc {
|
||||||
avatar = "/static/img/shy-friends.png"
|
avatar = "/static/img/shy-friends.png"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Country flag emoji.
|
||||||
|
emoji, err := geoip.GetRequestCountryFlag(r)
|
||||||
|
if err != nil {
|
||||||
|
emoji, err = geoip.CountryFlagEmojiWithCode("US")
|
||||||
|
if err != nil {
|
||||||
|
emoji = "🏴☠️"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create the JWT claims.
|
// Create the JWT claims.
|
||||||
claims := Claims{
|
claims := Claims{
|
||||||
IsAdmin: currentUser.HasAdminScope(config.ScopeChatModerator),
|
IsAdmin: currentUser.HasAdminScope(config.ScopeChatModerator),
|
||||||
Avatar: avatar,
|
Avatar: avatar,
|
||||||
ProfileURL: "/u/" + currentUser.Username,
|
ProfileURL: "/u/" + currentUser.Username,
|
||||||
Nickname: currentUser.NameOrUsername(),
|
Nickname: currentUser.NameOrUsername(),
|
||||||
|
Emoji: emoji,
|
||||||
|
Gender: Gender(currentUser),
|
||||||
RegisteredClaims: jwt.RegisteredClaims{
|
RegisteredClaims: jwt.RegisteredClaims{
|
||||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(5 * time.Minute)),
|
ExpiresAt: jwt.NewNumericDate(time.Now().Add(5 * time.Minute)),
|
||||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||||
|
|
75
pkg/geoip/geoip.go
Normal file
75
pkg/geoip/geoip.go
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
// Package geoip provides IP address geolocation features.
|
||||||
|
package geoip
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"code.nonshy.com/nonshy/website/pkg/config"
|
||||||
|
"code.nonshy.com/nonshy/website/pkg/utility"
|
||||||
|
"github.com/oschwald/geoip2-golang"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetRequestCity returns the GeoIP City result for the current HTTP request.
|
||||||
|
func GetRequestCity(r *http.Request) (*geoip2.City, error) {
|
||||||
|
var (
|
||||||
|
addr = utility.IPAddress(r)
|
||||||
|
ip = net.ParseIP(addr)
|
||||||
|
)
|
||||||
|
return GetCity(ip)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRequestCountryFlag returns the country flag based on the current HTTP request IP address.
|
||||||
|
func GetRequestCountryFlag(r *http.Request) (string, error) {
|
||||||
|
city, err := GetRequestCity(r)
|
||||||
|
if err != nil {
|
||||||
|
// If the remote addr is localhost (local dev testing), default to US flag.
|
||||||
|
if addr := utility.IPAddress(r); addr == "127.0.0.1" || addr == "::1" {
|
||||||
|
return CountryFlagEmoji("US")
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return CountryFlagEmoji(city.Country.IsoCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCity queries the GeoIP database for city information for an IP address.
|
||||||
|
func GetCity(ip net.IP) (*geoip2.City, error) {
|
||||||
|
db, err := geoip2.Open(config.GeoIPPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return db.City(ip)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CountryFlagEmoji returns the emoji sequence for a country flag based on
|
||||||
|
// the two-letter country code.
|
||||||
|
func CountryFlagEmoji(alpha2 string) (string, error) {
|
||||||
|
if len(alpha2) != 2 {
|
||||||
|
return "", errors.New("country code must be two letters long")
|
||||||
|
}
|
||||||
|
|
||||||
|
alpha2 = strings.ToLower(alpha2)
|
||||||
|
|
||||||
|
var (
|
||||||
|
flagBaseIndex = '\U0001F1E6' - 'a'
|
||||||
|
box = func(ch byte) string {
|
||||||
|
return string(rune(ch) + flagBaseIndex)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return string(box(alpha2[0]) + box(alpha2[1])), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CountryFlagEmojiWithCode returns a string consisting of the country flag, a space, and the alpha2 code passed in.
|
||||||
|
func CountryFlagEmojiWithCode(alpha2 string) (string, error) {
|
||||||
|
if emoji, err := CountryFlagEmoji(alpha2); err != nil {
|
||||||
|
return emoji, err
|
||||||
|
} else {
|
||||||
|
return emoji + " " + alpha2, nil
|
||||||
|
}
|
||||||
|
}
|
34
pkg/geoip/geoip_test.go
Normal file
34
pkg/geoip/geoip_test.go
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
package geoip_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"code.nonshy.com/nonshy/website/pkg/geoip"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCountryFlags(t *testing.T) {
|
||||||
|
table := []struct {
|
||||||
|
input string
|
||||||
|
expect string
|
||||||
|
err bool
|
||||||
|
}{
|
||||||
|
{"US", "🇺🇸", false},
|
||||||
|
{"CA", "🇨🇦", false},
|
||||||
|
{"AU", "🇦🇺", false},
|
||||||
|
{"NZ", "🇳🇿", false},
|
||||||
|
{"CN", "🇨🇳", false},
|
||||||
|
{"invalid", "", true},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range table {
|
||||||
|
emoji, err := geoip.CountryFlagEmoji(test.input)
|
||||||
|
if err != nil && !test.err {
|
||||||
|
t.Errorf("Country %s: got an error but did not expect to: %s", test.input, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if emoji != test.expect {
|
||||||
|
t.Errorf("Country %s: did not get expected emoji %s, got %+v", test.input, test.expect, emoji)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user