You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

281 lines
6.4 KiB

package altvr
import (
"log"
"net/http/cookiejar"
"golang.org/x/net/publicsuffix"
)
// XXX: Hold a HTTP CONNECT / Keep-Alive so we show up as online
// AltVR Client Type
type AltVR struct {
jar *cookiejar.Jar
username string
password string
csrfToken string // CSRF token for requests
userID string // Our own user id
user User // Cache of our own user data
friends []User
friendships []Friendship
onlineFriendships []Friendship
}
// DisconnectFunc handler for disconnection
type DisconnectFunc func(User)
// ConnectFunc handler for connection
type ConnectFunc func(User)
// New creates a new instance of the AltVR client
// Takes an account username and password as parameters
func New(u, p string) AltVR {
avr := AltVR{username: u, password: p}
var err error
avr.jar, err = cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List})
if err != nil {
log.Fatal(err)
}
err = avr.doLogin()
if err != nil {
log.Fatal(err)
}
user, err := avr.fetchMyUser()
if err != nil {
log.Fatal(err)
}
avr.user = user
if err := avr.FetchFriendships(); err != nil {
log.Fatal(err)
}
return avr
}
// GetAvatarURL returns the cached user avatar url
func (avr *AltVR) GetAvatarURL() string {
return avr.user.ProfileImage
}
// FetchMyUser fetches our own user data and cache it
func (avr *AltVR) FetchMyUser() error {
user, err := avr.fetchMyUser()
if err == errorLogin {
log.Println("Not logged in, doing login")
err = avr.doLogin()
if err != nil {
log.Fatal(err)
}
user, err = avr.fetchMyUser()
}
if err != nil {
return err
}
avr.user = user
return nil
}
// GetMyUser Returns the cached copy of our user data
func (avr *AltVR) GetMyUser() User {
return avr.user
}
// FetchClientIP retrives the client IP from the API
func (avr *AltVR) FetchClientIP() (string, error) {
return avr.fetchClientIP()
}
// FetchFriendships fetches all our friends' user data and caches it
func (avr *AltVR) FetchFriendships() error {
var err error
friendships, err := avr.fetchFriendships()
if err != nil {
return err
}
for _, friendship := range friendships {
found := false
for _, ff := range avr.friendships {
if friendship.FriendID == ff.FriendID {
found = true
break
}
}
if !found {
if err := avr.FetchFriend(friendship.FriendID); err != nil {
log.Printf("Error fetching friend user data: %+v\n", err)
}
}
}
avr.friendships = friendships
return nil
}
// GetFriendships returns the cached list of friendships
func (avr *AltVR) GetFriendships() []Friendship {
return avr.friendships
}
// FetchOnlineFriendships check for changes in the online friends list
// Triggers the callback functions on dis/connect
func (avr *AltVR) FetchOnlineFriendships(cfn ConnectFunc, dfn DisconnectFunc) error {
friendships, err := avr.fetchFriendshipsOnline()
if err != nil {
return err
}
for _, friendship := range friendships {
found := false
for _, of := range avr.onlineFriendships {
if friendship.FriendID == of.FriendID {
found = true
break
}
}
if !found {
if err := avr.FetchFriend(friendship.FriendID); err != nil {
return err
}
cfn(avr.GetFriend(friendship.FriendID))
}
}
for _, friendship := range avr.onlineFriendships {
found := false
for _, of := range friendships {
if friendship.FriendID == of.FriendID {
found = true
break
}
}
if !found {
if err := avr.FetchFriend(friendship.FriendID); err != nil {
return err
}
dfn(avr.GetFriend(friendship.FriendID))
}
}
avr.onlineFriendships = friendships
return nil
}
// FetchFriend fetches one user's data and update the cache
func (avr *AltVR) FetchFriend(userID string) error {
users, err := avr.fetchUsers(userID)
if err != nil {
return err
}
user := users[0]
found := false
for k, u := range avr.friends {
if u.UserID == user.UserID {
avr.friends[k] = user
found = true
break
}
}
if !found {
avr.friends = append(avr.friends, user)
}
return nil
}
// FetchFriends fetches many users' data and update the cache
func (avr *AltVR) FetchFriends(userID ...string) error {
users, err := avr.fetchUsers(userID...)
if err != nil {
return err
}
for _, user := range users {
found := false
for k, u := range avr.friends {
if u.UserID == user.UserID {
avr.friends[k] = user
found = true
break
}
}
if !found {
avr.friends = append(avr.friends, user)
}
}
return nil
}
// GetFriend gets a cached friend user data with the user ID
func (avr *AltVR) GetFriend(userID string) User {
var user User
for _, u := range avr.friends {
if u.UserID == userID {
user = u
break
}
}
return user
}
// GetFriendByUsername gets a cached friend user data with the username
func (avr *AltVR) GetFriendByUsername(username string) User {
var user User
for _, u := range avr.friends {
if u.Username == username {
user = u
break
}
}
return user
}
// FetchPendingFriendshipRequests fetches a list of pending friendship requests
func (avr *AltVR) FetchPendingFriendshipRequests() ([]Friendship, error) {
fr, err := avr.fetchPendingFriendshipRequests()
if err != nil {
log.Printf("Error fetching pending conversations: %+v\n", err)
return fr, err
}
var uids []string
for _, ff := range fr {
uids = append(uids, ff.UserID)
}
avr.FetchFriends(uids...)
return fr, nil
}
// AcceptFriendshipRequest accepts a pending friendship request
func (avr *AltVR) AcceptFriendshipRequest(FriendshipID string) error {
return avr.acceptPendingFriendshipRequest(FriendshipID)
}
// DenyFriendshipRequest accepts a pending friendship request
func (avr *AltVR) DenyFriendshipRequest(FriendshipID string) error {
return avr.denyPendingFriendshipRequest(FriendshipID)
}
// FetchPendingConversations fetches any pending conversations
func (avr *AltVR) FetchPendingConversations() ([]Conversation, error) {
pc, err := avr.fetchPendingConversations()
if err != nil {
log.Printf("Error fetching pending conversations: %+v\n", err)
return pc, err
}
var ccs []Conversation
for _, c := range pc {
if !c.IsRead {
ccs = append(ccs, c)
}
}
return ccs, nil
}
// AcknowkledgeConversation mark a conversation item as read
func (avr *AltVR) AcknowkledgeConversation(conversationID string) error {
return avr.markConversationAsRead(conversationID)
}
// PostNewConversation send a new message
func (avr *AltVR) PostNewConversation(userID, message string) error {
// XXX: Truncate 140 chars
return avr.postNewConversation(userID, message)
}