diff --git a/database/frienddb.sql b/database/frienddb.sql index d7515a8a..a18abdc3 100644 --- a/database/frienddb.sql +++ b/database/frienddb.sql @@ -1,13 +1,3 @@ --- MySQL dump 10.14 Distrib 5.5.41-MariaDB, for Linux (x86_64) --- --- Host: localhost Database: frienddb --- ------------------------------------------------------ --- Server version 5.5.41-MariaDB - --- --- Table structure for table `version` --- - DROP TABLE IF EXISTS `version`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -19,6 +9,7 @@ CREATE TABLE `version` ( ) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; /*!40101 SET character_set_client = @saved_cs_client */; +-- 好友相关 -- drop table if exists `t_friend_ships`; CREATE TABLE `t_friend_ships` ( `idx` bigint NOT NULL AUTO_INCREMENT COMMENT '自增id', @@ -43,4 +34,49 @@ flag tinyint DEFAULT '0' COMMENT '0 pending, 1 ok, 2 reject', `modifytime` int NOT NULL DEFAULT '0' COMMENT '修改时间', PRIMARY KEY (`idx`), UNIQUE KEY `friend_req` (`sender_account_id`,`receiver_account_id`) -) COMMENT "等待验证的好友请求"; \ No newline at end of file +) COMMENT "等待验证的好友请求"; + +-- 公会相关 -- +drop table if exists t_guild; +CREATE TABLE t_guild ( +`idx` bigint NOT NULL AUTO_INCREMENT COMMENT '自增id', +name VARCHAR(255) NOT NULL, +leader_id VARCHAR(255) NOT NULL, +max_members INT DEFAULT "0", +level INT default "0", +exp INT default "0", +badge INT default "0", +`createtime` int NOT NULL DEFAULT '0' COMMENT '创建时间', +`modifytime` int NOT NULL DEFAULT '0' COMMENT '修改时间', +PRIMARY KEY (`idx`), +UNIQUE KEY `guild_name` (`name`,`leader_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin +COMMENT "公会表" +; + +drop table if exists t_guild_members; +CREATE TABLE t_guild_members ( +guild_id INT NOT NULL, +account_id VARCHAR(255) NOT NULL, +`createtime` int NOT NULL DEFAULT '0' COMMENT '创建时间', +`modifytime` int NOT NULL DEFAULT '0' COMMENT '修改时间', +PRIMARY KEY (`guild_id`, `account_id`), +key createtime(`createtime`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin +COMMENT "公会成员表" +; + +drop table if exists t_guild_logs; +CREATE TABLE t_guild_logs ( +`idx` bigint NOT NULL AUTO_INCREMENT COMMENT '自增id', +guild_id INT NOT NULL, +account_id VARCHAR(255) NOT NULL, +log_type tinyint NOT NULL default '0' COMMENT "日志类型", +`createtime` int NOT NULL DEFAULT '0' COMMENT '创建时间', +`modifytime` int NOT NULL DEFAULT '0' COMMENT '修改时间', +PRIMARY KEY (`idx`), +key guild_name(`guild_id`, `account_id`, `log_type`), +key createtime(`createtime`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin +COMMENT "公会日志表" +; \ No newline at end of file diff --git a/server/imserver/guild.go b/server/imserver/guild.go new file mode 100644 index 00000000..5356cd2c --- /dev/null +++ b/server/imserver/guild.go @@ -0,0 +1,86 @@ +package main + +import "errors" + +type GuildMember struct { + AccountId string + Username string + Level int // 1: 会长, 2: 干部, 3: 成员 +} + +type Guild struct { + ID string + Name string + LeaderID string + Members []GuildMember + MaxMembers int +} + +func (g *Guild) findMemberIndex(AccountId string) int { + for i, member := range g.Members { + if member.AccountId == AccountId { + return i + } + } + return -1 +} + +// AddMember 添加成员 +func (g *Guild) AddMember(member GuildMember) error { + if len(g.Members) >= g.MaxMembers { + return errors.New("guild is full") + } + g.Members = append(g.Members, member) + return nil +} + +// RemoveMember 移除成员 +func (g *Guild) RemoveMember(accountId string) error { + if accountId == g.LeaderID { + return errors.New("cannot remove leader") + } + + index := g.findMemberIndex(accountId) + if index == -1 { + return errors.New("member not found") + } + + g.Members = append(g.Members[:index], g.Members[index+1:]...) + return nil +} + +// PromoteMember 提升成员为干部 +func (g *Guild) PromoteMember(accountId string) error { + if accountId == g.LeaderID { + return errors.New("cannot promote leader") + } + + index := g.findMemberIndex(accountId) + if index == -1 { + return errors.New("member not found") + } + + g.Members[index].Level = 2 + return nil +} + +// DemoteMember 解除成员干部身份 +func (g *Guild) DemoteMember(accountId string) error { + if accountId == g.LeaderID { + return errors.New("cannot demote leader") + } + + index := g.findMemberIndex(accountId) + if index == -1 { + return errors.New("member not found") + } + + g.Members[index].Level = 3 + return nil +} + +// Disband 解散公会 +func (g *Guild) Disband() error { + // 清空成员列表等解散公会 + return nil +} diff --git a/server/imserver/guildmgr.go b/server/imserver/guildmgr.go new file mode 100644 index 00000000..4de386a8 --- /dev/null +++ b/server/imserver/guildmgr.go @@ -0,0 +1,231 @@ +package main + +import ( + "cs" + "errors" +) + +type GuildMgr struct { + cs.MsgHandlerImpl + Guilds map[string]*Guild // 公会ID -> 公会列表 + pendingAccountIds map[string][]string // 公会ID -> 申请者账户ID列表 + Logs []string // 公会日志 +} + +func NewGuildMgr() *GuildMgr { + return &GuildMgr{ + Guilds: make(map[string]*Guild), + pendingAccountIds: make(map[string][]string), + Logs: []string{}, + } +} + +// CreateGuild 创建公会 +func (gm *GuildMgr) CreateGuild(name string, leaderID string, maxMembers int) (string, error) { + if maxMembers <= 0 { + return "", errors.New("invalid maxMembers") + } + + guildID := "123" + + if _, exists := gm.Guilds[guildID]; exists { + return "", errors.New("guild already exists") + } + + newGuild := &Guild{ + ID: guildID, + Name: name, + LeaderID: leaderID, + MaxMembers: maxMembers, + } + + gm.Guilds[guildID] = newGuild + return guildID, nil +} + +// ApplyToGuild 申请加入公会 +func (gm *GuildMgr) ApplyToGuild(guildID string, applicantID string) error { + if _, exists := gm.Guilds[guildID]; !exists { + return errors.New("guild not found") + } + + guild := gm.Guilds[guildID] + if len(guild.Members) >= guild.MaxMembers { + return errors.New("guild is full") + } + + gm.pendingAccountIds[guildID] = append(gm.pendingAccountIds[guildID], applicantID) + return nil +} + +// ApproveApplication 批准申请加入公会 +func (gm *GuildMgr) ApproveApplication(guildID string, applicantID string) error { + guild, exists := gm.Guilds[guildID] + if !exists { + return errors.New("guild not found") + } + + applicants, pendingExists := gm.pendingAccountIds[guildID] + if !pendingExists { + return errors.New("no pending applications for this guild") + } + + for i, appID := range applicants { + if appID == applicantID { + newMember := GuildMember{AccountId: applicantID, Username: applicantID, Level: 3} + guild.Members = append(guild.Members, newMember) + gm.pendingAccountIds[guildID] = append(applicants[:i], applicants[i+1:]...) + return nil + } + } + + return errors.New("applicant not found") +} + +// RejectApplication 拒绝申请加入公会 +func (gm *GuildMgr) RejectApplication(guildID string, applicantID string) error { + applicants, exists := gm.pendingAccountIds[guildID] + if !exists { + return errors.New("no pending applications for this guild") + } + + for i, appID := range applicants { + if appID == applicantID { + gm.pendingAccountIds[guildID] = append(applicants[:i], applicants[i+1:]...) + return nil + } + } + + return errors.New("applicant not found") +} + +// JoinGuild 加入公会 +func (gm *GuildMgr) JoinGuild(guildID, memberID string) error { + guild, exists := gm.Guilds[guildID] + if !exists { + return errors.New("guild not found") + } + + if len(guild.Members) >= guild.MaxMembers { + return errors.New("guild is full") + } + + newMember := GuildMember{AccountId: memberID, Username: memberID, Level: 3} + guild.Members = append(guild.Members, newMember) + return nil +} + +// LeaveGuild 离开公会 +func (gm *GuildMgr) LeaveGuild(guildID string, memberID string) error { + guild, exists := gm.Guilds[guildID] + if !exists { + return errors.New("guild not found") + } + + for i, member := range guild.Members { + if member.AccountId == memberID { + guild.Members = append(guild.Members[:i], guild.Members[i+1:]...) + return nil + } + } + + return errors.New("member not found in the guild") +} + +// DismissMember 开除成员 +func (gm *GuildMgr) DismissMember(guildID string, memberID string) error { + guild, exists := gm.Guilds[guildID] + if !exists { + return errors.New("guild not found") + } + + if memberID == guild.LeaderID { + return errors.New("cannot dismiss the leader") + } + + for i, member := range guild.Members { + if member.AccountId == memberID { + guild.Members = append(guild.Members[:i], guild.Members[i+1:]...) + return nil + } + } + + return errors.New("member not found in the guild") +} + +// PromoteMember 提升成员为干部 +func (gm *GuildMgr) PromoteMember(guildID string, memberID string) error { + guild, exists := gm.Guilds[guildID] + if !exists { + return errors.New("guild not found") + } + + if memberID == guild.LeaderID { + return errors.New("cannot promote the leader") + } + + for _, member := range guild.Members { + if member.AccountId == memberID { + member.Level = 2 + return nil + } + } + + return errors.New("member not found in the guild") +} + +// DemoteMember 解除成员干部身份 +func (gm *GuildMgr) DemoteMember(guildID string, memberID string) error { + guild, exists := gm.Guilds[guildID] + if !exists { + return errors.New("guild not found") + } + + if memberID == guild.LeaderID { + return errors.New("cannot demote the leader") + } + + for _, member := range guild.Members { + if member.AccountId == memberID { + member.Level = 3 + return nil + } + } + + return errors.New("member not found in the guild") +} + +// WriteLog 记录公会日志 +func (gm *GuildMgr) WriteLog(logEntry string) { +} + +// SearchGuilds 根据关键字搜索公会 +func (gm *GuildMgr) SearchGuilds(keyword string) []Guild { + var results []Guild + for _, guild := range gm.Guilds { + if containsSubstring(guild.Name, keyword) { + results = append(results, *guild) + } + } + return results +} + +// RandomGuilds 随机显示公会 +func (gm *GuildMgr) RandomGuilds() []Guild { + //const numRandomGuilds = 10 + //count := len(gm.Guilds) + //if count <= numRandomGuilds { + // return gm.Guilds + //} + //randIndices := rand.Perm(count)[:numRandomGuilds] + //var results []Guild + //for _, idx := range randIndices { + // results = append(results, gm.Guilds[idx]) + //} + //return results + return nil +} + +func containsSubstring(s, substr string) bool { + return len(s) >= len(substr) && s[len(s)-len(substr):] == substr +} diff --git a/server/imserver/guildmgr_test.go b/server/imserver/guildmgr_test.go new file mode 100644 index 00000000..39ef256e --- /dev/null +++ b/server/imserver/guildmgr_test.go @@ -0,0 +1,65 @@ +package main + +import ( + "fmt" + "testing" +) + +func TestGuild(t *testing.T) { + // Test the basic functionality + guildMgr := NewGuildMgr() + + leaderID := "leader_account_id" + memberID := "member_account_id" + + guildID, err := guildMgr.CreateGuild("Awesome Guild", leaderID, 10) + if err != nil { + fmt.Println("Error:", err) + return + } + fmt.Println("Created guild:", guildID) + + err = guildMgr.ApplyToGuild(guildID, memberID) + if err != nil { + fmt.Println("Error:", err) + return + } + fmt.Println("Applied to guild") + + err = guildMgr.ApproveApplication(guildID, memberID) + if err != nil { + fmt.Println("Error:", err) + return + } + fmt.Println("Approved application") + + err = guildMgr.JoinGuild(guildID, memberID) + if err != nil { + fmt.Println("Error:", err) + return + } + fmt.Println("Joined guild") + + err = guildMgr.PromoteMember(guildID, memberID) + if err != nil { + fmt.Println("Error:", err) + return + } + fmt.Println("Promoted member") + + err = guildMgr.LeaveGuild(guildID, memberID) + if err != nil { + fmt.Println("Error:", err) + return + } + fmt.Println("Left guild") + + err = guildMgr.DismissMember(guildID, memberID) + if err != nil { + fmt.Println("Error:", err) + return + } + fmt.Println("Dismissed member") + + fmt.Println("Guild logs:", guildMgr.Logs) +}