mirror of
https://github.com/mautrix/whatsapp.git
synced 2025-03-14 14:15:38 +00:00
Force history sync when list-groups command is used or group listing methods are called directly
This commit is contained in:
parent
cceb4b8f1c
commit
48b6d327b6
2 changed files with 290 additions and 43 deletions
|
@ -41,6 +41,7 @@ import (
|
|||
|
||||
waBinary "go.mau.fi/whatsmeow/binary"
|
||||
|
||||
"go.mau.fi/util/jsontime"
|
||||
_ "go.mau.fi/util/jsontime"
|
||||
"maunium.net/go/mautrix/bridge/status"
|
||||
"maunium.net/go/mautrix/bridgev2"
|
||||
|
@ -51,17 +52,24 @@ import (
|
|||
|
||||
// WhatsAppGroup contains basic information about a WhatsApp group
|
||||
type WhatsAppGroup struct {
|
||||
ID string
|
||||
Name string
|
||||
Topic string
|
||||
Participants []WhatsAppParticipant
|
||||
ID string
|
||||
Name string
|
||||
Topic string
|
||||
IsParent bool
|
||||
Participants []WhatsAppParticipant
|
||||
MemberAddMode string
|
||||
DefaultMembershipApprovalMode string
|
||||
}
|
||||
|
||||
// WhatsAppParticipant contains information about a participant in a WhatsApp group
|
||||
type WhatsAppParticipant struct {
|
||||
ID string
|
||||
Name string
|
||||
IsAdmin bool
|
||||
ID string
|
||||
Name string
|
||||
IsAdmin bool
|
||||
IsSuperAdmin bool
|
||||
DisplayName string
|
||||
Error string
|
||||
AddRequest bool
|
||||
}
|
||||
|
||||
func (wa *WhatsAppConnector) LoadUserLogin(_ context.Context, login *bridgev2.UserLogin) error {
|
||||
|
@ -370,6 +378,17 @@ func (wa *WhatsAppClient) GetJoinedGroups(ctx context.Context) ([]WhatsAppGroup,
|
|||
return nil, errors.New("not connected to WhatsApp")
|
||||
}
|
||||
|
||||
// Set LastHistorySync to 24 hours ago to force a new sync
|
||||
loginMetadata := wa.UserLogin.Metadata.(*waid.UserLoginMetadata)
|
||||
loginMetadata.LastHistorySync = jsontime.Unix{Time: time.Now().Add(-24 * time.Hour)}
|
||||
wa.UserLogin.Log.Debug().Time("history_sync_reset_to", loginMetadata.LastHistorySync.Time).Msg("Reset LastHistorySync to 24 hours ago for GetJoinedGroups")
|
||||
|
||||
// Save the updated metadata
|
||||
err := wa.UserLogin.Save(ctx)
|
||||
if err != nil {
|
||||
wa.UserLogin.Log.Err(err).Msg("Failed to save updated LastHistorySync timestamp")
|
||||
}
|
||||
|
||||
// Get list of joined groups from whatsmeow
|
||||
whatsmeowGroups, err := wa.Client.GetJoinedGroups()
|
||||
if err != nil {
|
||||
|
@ -379,18 +398,42 @@ func (wa *WhatsAppClient) GetJoinedGroups(ctx context.Context) ([]WhatsAppGroup,
|
|||
// Convert whatsmeow types to our interface types
|
||||
groups := make([]WhatsAppGroup, len(whatsmeowGroups))
|
||||
for i, g := range whatsmeowGroups {
|
||||
groups[i] = WhatsAppGroup{
|
||||
ID: g.JID.String(),
|
||||
Name: g.Name,
|
||||
Topic: g.Topic,
|
||||
// Access group policy fields directly
|
||||
memberAddMode := string(g.MemberAddMode)
|
||||
defaultApprovalMode := ""
|
||||
if g.GroupParent.IsParent {
|
||||
defaultApprovalMode = g.GroupParent.DefaultMembershipApprovalMode
|
||||
}
|
||||
|
||||
// Add participants
|
||||
groups[i] = WhatsAppGroup{
|
||||
ID: g.JID.String(),
|
||||
Name: g.Name,
|
||||
Topic: g.Topic,
|
||||
IsParent: g.IsParent,
|
||||
MemberAddMode: memberAddMode,
|
||||
DefaultMembershipApprovalMode: defaultApprovalMode,
|
||||
}
|
||||
|
||||
// Add participants with more details
|
||||
groups[i].Participants = make([]WhatsAppParticipant, len(g.Participants))
|
||||
for j, p := range g.Participants {
|
||||
// Convert error int to string
|
||||
errorStr := ""
|
||||
if p.Error != 0 {
|
||||
errorStr = fmt.Sprintf("%d", p.Error)
|
||||
}
|
||||
|
||||
// Check if AddRequest is present
|
||||
hasAddRequest := p.AddRequest != nil
|
||||
|
||||
groups[i].Participants[j] = WhatsAppParticipant{
|
||||
Name: p.JID.User, // Just use JID username as name
|
||||
IsAdmin: p.IsAdmin,
|
||||
ID: p.JID.String(),
|
||||
Name: p.JID.User,
|
||||
IsAdmin: p.IsAdmin,
|
||||
IsSuperAdmin: p.IsSuperAdmin,
|
||||
DisplayName: p.DisplayName,
|
||||
Error: errorStr,
|
||||
AddRequest: hasAddRequest,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -405,30 +448,91 @@ func (wa *WhatsAppClient) GetFormattedGroups(ctx context.Context) (string, error
|
|||
return "", errors.New("not connected to WhatsApp")
|
||||
}
|
||||
|
||||
// Set LastHistorySync to 24 hours ago to force a new sync
|
||||
loginMetadata := wa.UserLogin.Metadata.(*waid.UserLoginMetadata)
|
||||
loginMetadata.LastHistorySync = jsontime.Unix{Time: time.Now().Add(-24 * time.Hour)}
|
||||
wa.UserLogin.Log.Debug().Time("history_sync_reset_to", loginMetadata.LastHistorySync.Time).Msg("Reset LastHistorySync to 24 hours ago for GetFormattedGroups")
|
||||
|
||||
// Save the updated metadata
|
||||
err := wa.UserLogin.Save(ctx)
|
||||
if err != nil {
|
||||
wa.UserLogin.Log.Err(err).Msg("Failed to save updated LastHistorySync timestamp")
|
||||
}
|
||||
|
||||
// Get current user's JID
|
||||
userWANumber := wa.JID.User
|
||||
|
||||
// Get list of joined groups from whatsmeow
|
||||
groups, err := wa.Client.GetJoinedGroups()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get joined groups: %w", err)
|
||||
}
|
||||
|
||||
// Handle empty groups case
|
||||
if len(groups) == 0 {
|
||||
return "[]", nil
|
||||
wrapper := map[string]interface{}{
|
||||
"schema": "basic",
|
||||
"userWANumber": userWANumber,
|
||||
"data": []map[string]interface{}{},
|
||||
}
|
||||
jsonData, err := json.Marshal(wrapper)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to marshal groups to JSON: %w", err)
|
||||
}
|
||||
return string(jsonData), nil
|
||||
}
|
||||
|
||||
// Create a slice of map entries for JSON marshaling, filtering out parent groups
|
||||
// Filter and create a slice of group data
|
||||
var jsonGroups []map[string]interface{}
|
||||
for _, group := range groups {
|
||||
if !group.IsParent {
|
||||
jsonGroups = append(jsonGroups, map[string]interface{}{
|
||||
"jid": group.JID.String(),
|
||||
"name": group.Name,
|
||||
"participantCount": len(group.Participants),
|
||||
})
|
||||
// Skip groups with less than 3 members and not parent groups
|
||||
if len(group.Participants) < 3 && !group.IsParent {
|
||||
continue
|
||||
}
|
||||
|
||||
// For parent groups, check if the user is a participant
|
||||
if group.IsParent {
|
||||
isUserParticipant := false
|
||||
for _, p := range group.Participants {
|
||||
if p.JID.User == userWANumber {
|
||||
isUserParticipant = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !isUserParticipant {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Create basic group data
|
||||
groupData := map[string]interface{}{
|
||||
"jid": group.JID.String(),
|
||||
"name": group.Name,
|
||||
"participantCount": len(group.Participants),
|
||||
}
|
||||
|
||||
// Include additional group details for better context
|
||||
groupData["memberAddMode"] = string(group.MemberAddMode)
|
||||
groupData["joinApprovalRequired"] = group.GroupMembershipApprovalMode.IsJoinApprovalRequired
|
||||
|
||||
// Include parent group info if applicable
|
||||
if group.GroupParent.IsParent {
|
||||
groupData["isParentGroup"] = true
|
||||
groupData["defaultMembershipApprovalMode"] = group.GroupParent.DefaultMembershipApprovalMode
|
||||
}
|
||||
|
||||
jsonGroups = append(jsonGroups, groupData)
|
||||
}
|
||||
|
||||
// Create wrapper with schema, userWANumber, and data
|
||||
wrapper := map[string]interface{}{
|
||||
"schema": "basic",
|
||||
"userWANumber": userWANumber,
|
||||
"data": jsonGroups,
|
||||
}
|
||||
|
||||
// Marshal to JSON
|
||||
jsonData, err := json.Marshal(jsonGroups)
|
||||
jsonData, err := json.Marshal(wrapper)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to marshal groups to JSON: %w", err)
|
||||
}
|
||||
|
@ -438,34 +542,158 @@ func (wa *WhatsAppClient) GetFormattedGroups(ctx context.Context) (string, error
|
|||
|
||||
// SendGroupsToReMatchBackend sends the WhatsApp groups to the ReMatch backend
|
||||
func (wa *WhatsAppClient) SendGroupsToReMatchBackend(ctx context.Context) error {
|
||||
// Get the formatted JSON data
|
||||
formattedJSON, err := wa.GetFormattedGroups(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get formatted groups: %w", err)
|
||||
// Make sure the client is connected
|
||||
if wa.Client == nil || !wa.Client.IsLoggedIn() {
|
||||
return errors.New("not connected to WhatsApp")
|
||||
}
|
||||
|
||||
// Get the original groups data
|
||||
originalGroups, err := wa.GetJoinedGroups(ctx)
|
||||
// Set LastHistorySync to 24 hours ago to force a new sync
|
||||
loginMetadata := wa.UserLogin.Metadata.(*waid.UserLoginMetadata)
|
||||
loginMetadata.LastHistorySync = jsontime.Unix{Time: time.Now().Add(-24 * time.Hour)}
|
||||
wa.UserLogin.Log.Debug().Time("history_sync_reset_to", loginMetadata.LastHistorySync.Time).Msg("Reset LastHistorySync to 24 hours ago for SendGroupsToReMatchBackend")
|
||||
|
||||
// Save the updated metadata
|
||||
err := wa.UserLogin.Save(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get original groups: %w", err)
|
||||
wa.UserLogin.Log.Err(err).Msg("Failed to save updated LastHistorySync timestamp")
|
||||
// Continue execution even if save fails
|
||||
}
|
||||
|
||||
// Convert original groups to JSON
|
||||
originalJSON, err := json.Marshal(originalGroups)
|
||||
// Get the current user's JID
|
||||
userWANumber := wa.JID.User
|
||||
|
||||
// Get list of joined groups from whatsmeow
|
||||
whatsmeowGroups, err := wa.Client.GetJoinedGroups()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal original groups to JSON: %w", err)
|
||||
return fmt.Errorf("failed to get joined groups: %w", err)
|
||||
}
|
||||
|
||||
// Filter groups according to requirements
|
||||
var filteredGroups []*types.GroupInfo
|
||||
for _, group := range whatsmeowGroups {
|
||||
// Skip groups with less than 3 members and not parent groups
|
||||
if len(group.Participants) < 3 && !group.IsParent {
|
||||
continue
|
||||
}
|
||||
|
||||
// For parent groups, check if the user is a participant
|
||||
if group.IsParent {
|
||||
isUserParticipant := false
|
||||
for _, p := range group.Participants {
|
||||
if p.JID.User == userWANumber {
|
||||
isUserParticipant = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !isUserParticipant {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
filteredGroups = append(filteredGroups, group)
|
||||
}
|
||||
|
||||
// Get the formatted JSON data for basic schema
|
||||
formattedGroups := make([]map[string]interface{}, len(filteredGroups))
|
||||
for i, group := range filteredGroups {
|
||||
// Create a basic group object with minimal information
|
||||
formattedGroups[i] = map[string]interface{}{
|
||||
"jid": group.JID.String(),
|
||||
"name": group.Name,
|
||||
"participantCount": len(group.Participants),
|
||||
}
|
||||
}
|
||||
|
||||
// Create detailed original data for raw schema
|
||||
originalGroups := make([]map[string]interface{}, len(filteredGroups))
|
||||
for i, group := range filteredGroups {
|
||||
// Process participants
|
||||
participants := make([]map[string]interface{}, len(group.Participants))
|
||||
for j, p := range group.Participants {
|
||||
// Convert error code to string if present
|
||||
errorStr := ""
|
||||
if p.Error != 0 {
|
||||
errorStr = fmt.Sprintf("%d", p.Error)
|
||||
}
|
||||
|
||||
// Check if AddRequest exists
|
||||
hasAddRequest := p.AddRequest != nil
|
||||
|
||||
participants[j] = map[string]interface{}{
|
||||
"jid": p.JID.String(),
|
||||
"name": p.JID.User,
|
||||
"isAdmin": p.IsAdmin,
|
||||
"isSuperAdmin": p.IsSuperAdmin,
|
||||
"displayName": p.DisplayName,
|
||||
"error": errorStr,
|
||||
"addRequest": hasAddRequest,
|
||||
}
|
||||
}
|
||||
|
||||
// Create group data with all available information
|
||||
groupData := map[string]interface{}{
|
||||
"jid": group.JID.String(),
|
||||
"name": group.Name,
|
||||
"topic": group.Topic,
|
||||
"isParent": group.IsParent,
|
||||
"participants": participants,
|
||||
"memberAddMode": string(group.MemberAddMode),
|
||||
"created": group.GroupCreated.Format(time.RFC3339),
|
||||
"joinApprovalRequired": group.GroupMembershipApprovalMode.IsJoinApprovalRequired,
|
||||
}
|
||||
|
||||
// Include parent information if available
|
||||
if group.GroupParent.IsParent {
|
||||
groupData["isParentGroup"] = true
|
||||
groupData["defaultMembershipApprovalMode"] = group.GroupParent.DefaultMembershipApprovalMode
|
||||
}
|
||||
|
||||
// Include linked parent JID if available
|
||||
if !group.GroupLinkedParent.LinkedParentJID.IsEmpty() {
|
||||
groupData["linkedParentJID"] = group.GroupLinkedParent.LinkedParentJID.String()
|
||||
}
|
||||
|
||||
// Include owner JID if available
|
||||
if !group.OwnerJID.IsEmpty() {
|
||||
groupData["ownerJID"] = group.OwnerJID.String()
|
||||
}
|
||||
|
||||
originalGroups[i] = groupData
|
||||
}
|
||||
|
||||
// Create schema wrappers with userWANumber at the top level
|
||||
basicSchema := map[string]interface{}{
|
||||
"schema": "basic",
|
||||
"userWANumber": userWANumber,
|
||||
"data": formattedGroups,
|
||||
}
|
||||
|
||||
rawSchema := map[string]interface{}{
|
||||
"schema": "raw",
|
||||
"userWANumber": userWANumber,
|
||||
"data": originalGroups,
|
||||
}
|
||||
|
||||
// Marshal to JSON
|
||||
wrappedFormattedJSON, err := json.Marshal(basicSchema)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal basic schema: %w", err)
|
||||
}
|
||||
|
||||
wrappedOriginalJSON, err := json.Marshal(rawSchema)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal raw schema: %w", err)
|
||||
}
|
||||
|
||||
// ReMatch backend endpoint
|
||||
endpoint := "https://hkdk.events/ezl371xrvg6k52"
|
||||
|
||||
// Send the formatted JSON
|
||||
if err := sendJSONRequest(ctx, endpoint, formattedJSON); err != nil {
|
||||
// Send the JSON data to the endpoint
|
||||
if err := sendJSONRequest(ctx, endpoint, string(wrappedFormattedJSON)); err != nil {
|
||||
return fmt.Errorf("failed to send formatted groups: %w", err)
|
||||
}
|
||||
|
||||
// Send the original JSON
|
||||
if err := sendJSONRequest(ctx, endpoint, string(originalJSON)); err != nil {
|
||||
if err := sendJSONRequest(ctx, endpoint, string(wrappedOriginalJSON)); err != nil {
|
||||
return fmt.Errorf("failed to send original groups: %w", err)
|
||||
}
|
||||
|
||||
|
@ -474,14 +702,16 @@ func (wa *WhatsAppClient) SendGroupsToReMatchBackend(ctx context.Context) error
|
|||
|
||||
// Helper function to send JSON data to an endpoint
|
||||
func sendJSONRequest(ctx context.Context, endpoint string, jsonData string) error {
|
||||
// Create HTTP request
|
||||
// Create HTTP request with context for proper cancellation
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint, strings.NewReader(jsonData))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create request: %w", err)
|
||||
}
|
||||
|
||||
// Set proper content type header
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
// Send the request
|
||||
// Send the request with timeout
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
|
|
|
@ -19,7 +19,10 @@ package connector
|
|||
import (
|
||||
"maunium.net/go/mautrix/bridgev2/commands"
|
||||
|
||||
"time"
|
||||
|
||||
"go.mau.fi/mautrix-whatsapp/pkg/waid"
|
||||
"go.mau.fi/util/jsontime"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -78,10 +81,24 @@ func fnListGroups(ce *commands.Event) {
|
|||
ce.Reply("No WhatsApp account found. Please use !wa login to connect your WhatsApp account.")
|
||||
} else if !login.Client.IsLoggedIn() {
|
||||
ce.Reply("Not logged in")
|
||||
} else if err := login.Client.(*WhatsAppClient).SendGroupsToReMatchBackend(ce.Ctx); err != nil {
|
||||
ce.Log.Err(err).Msg("Failed to send groups to ReMatch backend")
|
||||
ce.Reply("Failed to send groups to ReMatch backend: %v", err)
|
||||
} else {
|
||||
ce.Reply("Successfully sent your WhatsApp groups to ReMatch backend.")
|
||||
// Set LastHistorySync to 24 hours ago to force a new sync
|
||||
loginMetadata := login.Metadata.(*waid.UserLoginMetadata)
|
||||
loginMetadata.LastHistorySync = jsontime.Unix{Time: time.Now().Add(-24 * time.Hour)}
|
||||
ce.Log.Debug().Time("history_sync_reset_to", loginMetadata.LastHistorySync.Time).Msg("Reset LastHistorySync to 24 hours ago")
|
||||
|
||||
// Save the updated metadata
|
||||
err := login.Save(ce.Ctx)
|
||||
if err != nil {
|
||||
ce.Log.Err(err).Msg("Failed to save updated LastHistorySync timestamp")
|
||||
}
|
||||
|
||||
// Proceed with sending groups to ReMatch backend
|
||||
if err := login.Client.(*WhatsAppClient).SendGroupsToReMatchBackend(ce.Ctx); err != nil {
|
||||
ce.Log.Err(err).Msg("Failed to send groups to ReMatch backend")
|
||||
ce.Reply("Failed to send groups to ReMatch backend: %v", err)
|
||||
} else {
|
||||
ce.Reply("Successfully sent your WhatsApp groups to ReMatch backend.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue