67 lines
2.2 KiB
Go
67 lines
2.2 KiB
Go
|
|
package domain
|
||
|
|
|
||
|
|
import "time"
|
||
|
|
|
||
|
|
const (
|
||
|
|
ConnectionConnected = "connected"
|
||
|
|
ConnectionError = "error"
|
||
|
|
ConnectionDisconnected = "disconnected"
|
||
|
|
)
|
||
|
|
|
||
|
|
// Account is a Threads OAuth binding (tokens server-only).
|
||
|
|
type Account struct {
|
||
|
|
ID string `bson:"_id" json:"id"`
|
||
|
|
OwnerUID int64 `bson:"owner_uid" json:"owner_uid"`
|
||
|
|
Username string `bson:"username" json:"username"`
|
||
|
|
DisplayName string `bson:"display_name" json:"display_name"`
|
||
|
|
ThreadsUserID string `bson:"threads_user_id" json:"threads_user_id"`
|
||
|
|
Connection string `bson:"connection" json:"connection"`
|
||
|
|
IsUsable bool `bson:"is_usable" json:"is_usable"`
|
||
|
|
AvatarColor string `bson:"avatar_color,omitempty" json:"avatar_color,omitempty"`
|
||
|
|
AvatarURL string `bson:"avatar_url,omitempty" json:"avatar_url,omitempty"`
|
||
|
|
ErrorMessage string `bson:"error_message,omitempty" json:"error_message,omitempty"`
|
||
|
|
SessionExpiresAt int64 `bson:"session_expires_at,omitempty" json:"session_expires_at,omitempty"`
|
||
|
|
SessionRefreshedAt int64 `bson:"session_refreshed_at,omitempty" json:"session_refreshed_at,omitempty"`
|
||
|
|
// Encrypted tokens — never expose via public DTO
|
||
|
|
AccessTokenEnc string `bson:"access_token_enc,omitempty" json:"-"`
|
||
|
|
RefreshTokenEnc string `bson:"refresh_token_enc,omitempty" json:"-"`
|
||
|
|
CreatedAt int64 `bson:"created_at" json:"created_at"`
|
||
|
|
UpdatedAt int64 `bson:"updated_at" json:"updated_at"`
|
||
|
|
}
|
||
|
|
|
||
|
|
// OAuthState binds CSRF state to member for callback.
|
||
|
|
type OAuthState struct {
|
||
|
|
State string `bson:"_id"`
|
||
|
|
OwnerUID int64 `bson:"owner_uid"`
|
||
|
|
CreatedAt int64 `bson:"created_at"`
|
||
|
|
ExpiresAt int64 `bson:"expires_at"`
|
||
|
|
}
|
||
|
|
|
||
|
|
// TokenPair from provider exchange (in-memory only).
|
||
|
|
type TokenPair struct {
|
||
|
|
AccessToken string
|
||
|
|
RefreshToken string
|
||
|
|
ExpiresIn int64 // seconds
|
||
|
|
UserID string
|
||
|
|
Username string
|
||
|
|
DisplayName string
|
||
|
|
AvatarURL string
|
||
|
|
}
|
||
|
|
|
||
|
|
func NowNano() int64 { return time.Now().UTC().UnixNano() }
|
||
|
|
|
||
|
|
func AvatarColorFor(username string) string {
|
||
|
|
colors := []string{"#6dbf7a", "#5b8def", "#e8a54b", "#c77dff", "#f07178"}
|
||
|
|
if username == "" {
|
||
|
|
return colors[0]
|
||
|
|
}
|
||
|
|
var h int
|
||
|
|
for _, r := range username {
|
||
|
|
h = (h*31 + int(r)) % len(colors)
|
||
|
|
}
|
||
|
|
if h < 0 {
|
||
|
|
h = -h
|
||
|
|
}
|
||
|
|
return colors[h%len(colors)]
|
||
|
|
}
|