212 lines
5.5 KiB
Go
212 lines
5.5 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/sjzar/chatlog/internal/model"
|
|
)
|
|
|
|
// initContactCache 初始化联系人缓存
|
|
func (r *Repository) initContactCache(ctx context.Context) error {
|
|
// 加载所有联系人到缓存
|
|
contacts, err := r.ds.GetContacts(ctx, "", 0, 0)
|
|
if err != nil {
|
|
return fmt.Errorf("加载联系人失败: %w", err)
|
|
}
|
|
|
|
contactMap := make(map[string]*model.Contact)
|
|
aliasMap := make(map[string]*model.Contact)
|
|
remarkMap := make(map[string]*model.Contact)
|
|
nickNameMap := make(map[string]*model.Contact)
|
|
chatRoomUserMap := make(map[string]*model.Contact)
|
|
chatRoomInContactMap := make(map[string]*model.Contact)
|
|
contactList := make([]string, 0)
|
|
aliasList := make([]string, 0)
|
|
remarkList := make([]string, 0)
|
|
nickNameList := make([]string, 0)
|
|
|
|
for _, contact := range contacts {
|
|
contactMap[contact.UserName] = contact
|
|
contactList = append(contactList, contact.UserName)
|
|
|
|
// 建立快速查找索引
|
|
if contact.Alias != "" {
|
|
aliasMap[contact.Alias] = contact
|
|
aliasList = append(aliasList, contact.Alias)
|
|
}
|
|
if contact.Remark != "" {
|
|
remarkMap[contact.Remark] = contact
|
|
remarkList = append(remarkList, contact.Remark)
|
|
}
|
|
if contact.NickName != "" {
|
|
nickNameMap[contact.NickName] = contact
|
|
nickNameList = append(nickNameList, contact.NickName)
|
|
}
|
|
|
|
// 如果是群聊成员(非好友),添加到群聊成员索引
|
|
if !contact.IsFriend {
|
|
chatRoomUserMap[contact.UserName] = contact
|
|
}
|
|
|
|
if strings.HasSuffix(contact.UserName, "@chatroom") {
|
|
chatRoomInContactMap[contact.UserName] = contact
|
|
}
|
|
}
|
|
|
|
sort.Strings(contactList)
|
|
sort.Strings(aliasList)
|
|
sort.Strings(remarkList)
|
|
sort.Strings(nickNameList)
|
|
|
|
r.contactCache = contactMap
|
|
r.aliasToContact = aliasMap
|
|
r.remarkToContact = remarkMap
|
|
r.nickNameToContact = nickNameMap
|
|
r.chatRoomUserToInfo = chatRoomUserMap
|
|
r.chatRoomInContact = chatRoomInContactMap
|
|
r.contactList = contactList
|
|
r.aliasList = aliasList
|
|
r.remarkList = remarkList
|
|
r.nickNameList = nickNameList
|
|
return nil
|
|
}
|
|
|
|
func (r *Repository) GetContact(ctx context.Context, key string) (*model.Contact, error) {
|
|
// 先尝试从缓存中获取
|
|
contact := r.findContact(key)
|
|
if contact == nil {
|
|
return nil, fmt.Errorf("未找到联系人: %s", key)
|
|
}
|
|
return contact, nil
|
|
}
|
|
|
|
func (r *Repository) GetContacts(ctx context.Context, key string, limit, offset int) ([]*model.Contact, error) {
|
|
ret := make([]*model.Contact, 0)
|
|
if key != "" {
|
|
ret = r.findContacts(key)
|
|
if len(ret) == 0 {
|
|
return nil, fmt.Errorf("未找到联系人: %s", key)
|
|
}
|
|
if limit > 0 {
|
|
end := offset + limit
|
|
if end > len(ret) {
|
|
end = len(ret)
|
|
}
|
|
if offset >= len(ret) {
|
|
return []*model.Contact{}, nil
|
|
}
|
|
return ret[offset:end], nil
|
|
}
|
|
} else {
|
|
list := r.contactList
|
|
if limit > 0 {
|
|
end := offset + limit
|
|
if end > len(list) {
|
|
end = len(list)
|
|
}
|
|
if offset >= len(list) {
|
|
return []*model.Contact{}, nil
|
|
}
|
|
list = list[offset:end]
|
|
}
|
|
for _, name := range list {
|
|
ret = append(ret, r.contactCache[name])
|
|
}
|
|
}
|
|
return ret, nil
|
|
}
|
|
|
|
func (r *Repository) findContact(key string) *model.Contact {
|
|
if contact, ok := r.contactCache[key]; ok {
|
|
return contact
|
|
}
|
|
if contact, ok := r.aliasToContact[key]; ok {
|
|
return contact
|
|
}
|
|
if contact, ok := r.remarkToContact[key]; ok {
|
|
return contact
|
|
}
|
|
if contact, ok := r.nickNameToContact[key]; ok {
|
|
return contact
|
|
}
|
|
|
|
// Contain
|
|
for _, alias := range r.aliasList {
|
|
if strings.Contains(alias, key) {
|
|
return r.aliasToContact[alias]
|
|
}
|
|
}
|
|
for _, remark := range r.remarkList {
|
|
if strings.Contains(remark, key) {
|
|
return r.remarkToContact[remark]
|
|
}
|
|
}
|
|
for _, nickName := range r.nickNameList {
|
|
if strings.Contains(nickName, key) {
|
|
return r.nickNameToContact[nickName]
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r *Repository) findContacts(key string) []*model.Contact {
|
|
ret := make([]*model.Contact, 0)
|
|
distinct := make(map[string]bool)
|
|
if contact, ok := r.contactCache[key]; ok {
|
|
ret = append(ret, contact)
|
|
distinct[contact.UserName] = true
|
|
}
|
|
if contact, ok := r.aliasToContact[key]; ok && !distinct[contact.UserName] {
|
|
ret = append(ret, contact)
|
|
distinct[contact.UserName] = true
|
|
}
|
|
if contact, ok := r.remarkToContact[key]; ok && !distinct[contact.UserName] {
|
|
ret = append(ret, contact)
|
|
distinct[contact.UserName] = true
|
|
}
|
|
if contact, ok := r.nickNameToContact[key]; ok && !distinct[contact.UserName] {
|
|
ret = append(ret, contact)
|
|
distinct[contact.UserName] = true
|
|
}
|
|
// Contain
|
|
for _, alias := range r.aliasList {
|
|
if strings.Contains(alias, key) && !distinct[r.aliasToContact[alias].UserName] {
|
|
ret = append(ret, r.aliasToContact[alias])
|
|
distinct[r.aliasToContact[alias].UserName] = true
|
|
}
|
|
}
|
|
for _, remark := range r.remarkList {
|
|
if strings.Contains(remark, key) && !distinct[r.remarkToContact[remark].UserName] {
|
|
ret = append(ret, r.remarkToContact[remark])
|
|
distinct[r.remarkToContact[remark].UserName] = true
|
|
}
|
|
}
|
|
for _, nickName := range r.nickNameList {
|
|
if strings.Contains(nickName, key) && !distinct[r.nickNameToContact[nickName].UserName] {
|
|
ret = append(ret, r.nickNameToContact[nickName])
|
|
distinct[r.nickNameToContact[nickName].UserName] = true
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
// getFullContact 获取联系人信息,包括群聊成员
|
|
func (r *Repository) getFullContact(userName string) *model.Contact {
|
|
// 先查找联系人缓存
|
|
if contact, ok := r.contactCache[userName]; ok {
|
|
return contact
|
|
}
|
|
|
|
// 再查找群聊成员缓存
|
|
contact, ok := r.chatRoomUserToInfo[userName]
|
|
|
|
if ok {
|
|
return contact
|
|
}
|
|
|
|
return nil
|
|
}
|