Merge remote-tracking branch 'upstream/main'

pull/2237/head
withchao 8 months ago
commit e601b5fca1

@ -25,6 +25,7 @@ jobs:
- name: Comment cherry-pick command
uses: actions/github-script@v7
with:
github-token: ${{ secrets.BOT_GITHUB_TOKEN }}
script: |
const pr = context.payload.pull_request;
if (!pr.merged) {
@ -63,5 +64,4 @@ jobs:
repo: context.repo.repo,
issue_number: pr.number,
body: cherryPickCmd
});
github-token: ${{ secrets.BOT_GITHUB_TOKEN }}
});

@ -12,23 +12,57 @@
# See the License for the specific language governing permissions and
# limitations under the License.
name: Github Rebot for Cherry Pick On Comment
name: Github Robot for Cherry Pick On Comment
on:
issue_comment:
types: [created]
jobs:
cherry-pick:
name: Cherry Pick
# && github.event.comment.user.login=='kubbot'
if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '/cherry-pick')
runs-on: ubuntu-latest
steps:
- name: Checkout the latest code
uses: actions/checkout@v4
with:
token: ${{ secrets.BOT_GITHUB_TOKEN }}
fetch-depth: 0 # otherwise, you will fail to push refs to dest repo
fetch-depth: 0 # To ensure all history is available for cherry-picking
- name: Automatic Cherry Pick
uses: vendoo/gha-cherry-pick@v1
with:
# Assuming the cherry-pick commit SHA is passed in the comment like '/cherry-pick sha'
commit-sha: ${{ github.event.comment.body }}
env:
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
- name: Create a new branch for PR
run: |
PR_BRANCH="cherry-pick-${GITHUB_SHA}-to-${{ github.base_ref }}"
git checkout -b $PR_BRANCH
git push origin $PR_BRANCH
env:
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
- name: Create Pull Request
uses: actions/github-script@v5
with:
script: |
const prTitle = "Cherry-pick to ${{ github.base_ref }}"
const prBody = "Automated cherry-pick of ${{ github.event.comment.body }}\n\n/cc @kubbot"
const base = "${{ github.base_ref }}"
const head = "cherry-pick-${{ github.sha }}-to-${{ github.base_ref }}"
const createPr = await github.rest.pulls.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: prTitle,
body: prBody,
head: head,
base: base,
maintainer_can_modify: true, // Allows maintainers to edit the PR
})
env:
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}

@ -0,0 +1,27 @@
# Copyright © 2024 OpenIM. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
name: Language Check Workflow Test
on: [pull_request]
jobs:
comment-language-detector:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Code Language Detector
uses: kubecub/comment-lang-detector@v1.0.0

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
name: OpenIM Linux System E2E Test
name: OpenIM E2E And API Test
on:
workflow_dispatch:
@ -82,7 +82,7 @@ jobs:
sudo make tidy
sudo make tools.verify.go-gitlint
- name: Build, Start
- name: Build, Start(make build && make start)
run: |
sudo ./scripts/install/install.sh -i
@ -90,9 +90,8 @@ jobs:
run: |
sudo ./scripts/install/install.sh -s
- name: Exec OpenIM API test
- name: Exec OpenIM API test (make test-api)
run: |
sudo make test-api
mkdir -p ./tmp
touch ./tmp/test.md
echo "# OpenIM Test" >> ./tmp/test.md
@ -103,9 +102,10 @@ jobs:
echo "</code></pre>" >> ./tmp/test.md
echo "</details>" >> ./tmp/test.md
- name: Exec OpenIM E2E Test
sudo make test-api
- name: Exec OpenIM E2E Test (make test-e2e)
run: |
sudo make test-e2e
echo "" >> ./tmp/test.md
echo "## OpenIM E2E Test" >> ./tmp/test.md
echo "<details><summary>Command Output for OpenIM E2E Test</summary>" >> ./tmp/test.md
@ -114,6 +114,8 @@ jobs:
echo "</code></pre>" >> ./tmp/test.md
echo "</details>" >> ./tmp/test.md
sudo make test-e2e
- name: Comment PR with file
uses: thollander/actions-comment-pull-request@v2
with:
@ -143,4 +145,4 @@ jobs:
PUBLISH_BRANCH: gh-pages
env:
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
continue-on-error: true
continue-on-error: true

@ -41,6 +41,7 @@ jobs:
steps:
- uses: actions/github-script@v7 # v6
with:
github-token: ${{ secrets.BOT_GITHUB_TOKEN }}
script: |
if (!context.payload.pull_request.merged) {
console.log('PR was not merged, skipping.');
@ -56,9 +57,10 @@ jobs:
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
sort: 'due_on',
direction: 'asc'
sort: 'title',
direction: 'desc'
})
if (milestones.data.length === 0) {
console.log('There are no milestones, skipping.');
return;

@ -745,7 +745,7 @@ linters:
- misspell # Spelling mistakes
- staticcheck # Static analysis
- unused # Checks for unused code
- goimports # Checks if imports are correctly sorted and formatted
# - goimports # Checks if imports are correctly sorted and formatted
- godot # Checks for comment punctuation
- bodyclose # Ensures HTTP response body is closed
- stylecheck # Style checker for Go code

@ -11,6 +11,7 @@ ENV GOPROXY=$GOPROXY
# Set up the working directory
WORKDIR /openim/openim-server
# Copy all files to the container
ADD . .

@ -143,7 +143,7 @@ KAFKA_LATESTMSG_REDIS_TOPIC=${KAFKA_LATESTMSG_REDIS_TOPIC}
# MINIO_PORT
# ----------
# MINIO_PORT sets the port for the MinIO object storage service.
# Upon changing this port, the MinIO endpoint URLs in the `config/config.yaml` file must be updated
# Upon changing this port, the MinIO endpoint URLs in the config/config.yaml file must be updated
# to reflect this change. The endpoints include both the 'endpoint' and 'signEndpoint'
# under the MinIO configuration.
#

@ -186,23 +186,6 @@ services:
# server:
# ipv4_address: ${OPENIM_SERVER_NETWORK_ADDRESS:-172.28.0.8}
### TODO: mysql is required to deploy the openim-chat component
# mysql:
# image: mysql:${MYSQL_IMAGE_VERSION:-5.7}
# platform: linux/amd64
# ports:
# - "${MYSQL_PORT:-13306}:3306"
# container_name: mysql
# volumes:
# - "${DATA_DIR:-./}/components/mysql/data:/var/lib/mysql"
# - "/etc/localtime:/etc/localtime"
# environment:
# MYSQL_ROOT_PASSWORD: "${MYSQL_PASSWORD:-openIM123}"
# restart: always
# networks:
# server:
# ipv4_address: ${MYSQL_NETWORK_ADDRESS:-172.28.0.15}
# openim-chat:
# image: ${IMAGE_REGISTRY:-ghcr.io/openimsdk}/openim-chat:${CHAT_IMAGE_VERSION:-main}
# container_name: openim-chat

@ -96,7 +96,6 @@ We reinforce our approach to branch management and versioning with stringent tes
This document describes the maximum version skew supported between various openim components. Specific cluster deployment tools may place additional restrictions on version skew.
### Supported version skew
In highly-available (HA) clusters, the newest and oldest `openim-api` instances must be within one minor version.
@ -210,6 +209,7 @@ git merge release-v3.1
# Push the updates to the main branch
git push origin main
```
## Release Process
```
@ -232,5 +232,7 @@ For more details on managing Docker image versions, visit [OpenIM Docker Images
More on multi-branch version management design and version management design at helm charts
+ https://github.com/openimsdk/open-im-server/issues/1695
+ https://github.com/openimsdk/open-im-server/issues/1662
About Helm's version management strategy for Multiple Apps and multiple Services:
+ [中文版本管理文档](https://github.com/openimsdk/helm-charts/blob/main/docs/contrib/version-zh.md)
+ [English version management documents](https://github.com/openimsdk/helm-charts/blob/main/docs/contrib/version.md)

@ -3,7 +3,6 @@ go 1.19
use (
.
./test/typecheck
./tools/codescan
./tools/changelog
./tools/component
./tools/formitychecker

@ -215,25 +215,22 @@ func (m *MessageApi) SendMessage(c *gin.Context) {
// Set the receiver ID in the message data.
sendMsgReq.MsgData.RecvID = req.RecvID
// Declare a variable to store the message sending status.
var status int
// Attempt to send the message using the client.
respPb, err := m.Client.SendMsg(c, sendMsgReq)
if err != nil {
// Set the status to failed and respond with an error if sending fails.
status = constant.MsgSendFailed
apiresp.GinError(c, err)
return
}
// Set the status to successful if the message is sent.
status = constant.MsgSendSuccessed
var status int = constant.MsgSendSuccessed
// Attempt to update the message sending status in the system.
_, err = m.Client.SetSendMsgStatus(c, &msg.SetSendMsgStatusReq{
Status: int32(status),
})
if err != nil {
// Log the error if updating the status fails.
apiresp.GinError(c, err)

@ -141,7 +141,6 @@ func (c *UserConnContext) GetBackground() bool {
b, err := strconv.ParseBool(c.Req.URL.Query().Get(BackgroundStatus))
if err != nil {
return false
} else {
return b
}
return b
}

@ -19,7 +19,6 @@ import (
"sync"
"github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/tools/utils"
)
type UserMap struct {
@ -71,48 +70,65 @@ func (u *UserMap) Set(key string, v *Client) {
}
func (u *UserMap) delete(key string, connRemoteAddr string) (isDeleteUser bool) {
// Attempt to load the clients associated with the key.
allClients, existed := u.m.Load(key)
if existed {
oldClients := allClients.([]*Client)
var a []*Client
for _, client := range oldClients {
if client.ctx.GetRemoteAddr() != connRemoteAddr {
a = append(a, client)
}
}
if len(a) == 0 {
u.m.Delete(key)
return true
} else {
u.m.Store(key, a)
return false
if !existed {
// Return false immediately if the key does not exist.
return false
}
// Convert allClients to a slice of *Client.
oldClients := allClients.([]*Client)
var remainingClients []*Client
for _, client := range oldClients {
// Keep clients that do not match the connRemoteAddr.
if client.ctx.GetRemoteAddr() != connRemoteAddr {
remainingClients = append(remainingClients, client)
}
}
return existed
// If no clients remain after filtering, delete the key from the map.
if len(remainingClients) == 0 {
u.m.Delete(key)
return true
}
// Otherwise, update the key with the remaining clients.
u.m.Store(key, remainingClients)
return false
}
func (u *UserMap) deleteClients(key string, clients []*Client) (isDeleteUser bool) {
m := utils.SliceToMapAny(clients, func(c *Client) (string, struct{}) {
return c.ctx.GetRemoteAddr(), struct{}{}
})
func (u *UserMap) deleteClients(key string, clientsToDelete []*Client) (isDeleteUser bool) {
// Convert the slice of clients to delete into a map for efficient lookup.
deleteMap := make(map[string]struct{})
for _, client := range clientsToDelete {
deleteMap[client.ctx.GetRemoteAddr()] = struct{}{}
}
// Load the current clients associated with the key.
allClients, existed := u.m.Load(key)
if existed {
oldClients := allClients.([]*Client)
var a []*Client
for _, client := range oldClients {
if _, ok := m[client.ctx.GetRemoteAddr()]; !ok {
a = append(a, client)
}
}
if len(a) == 0 {
u.m.Delete(key)
return true
} else {
u.m.Store(key, a)
return false
if !existed {
// If the key doesn't exist, return false.
return false
}
// Filter out clients that are in the deleteMap.
oldClients := allClients.([]*Client)
var remainingClients []*Client
for _, client := range oldClients {
if _, shouldBeDeleted := deleteMap[client.ctx.GetRemoteAddr()]; !shouldBeDeleted {
remainingClients = append(remainingClients, client)
}
}
return existed
// Update or delete the key based on the remaining clients.
if len(remainingClients) == 0 {
u.m.Delete(key)
return true
}
u.m.Store(key, remainingClients)
return false
}
func (u *UserMap) DeleteAll(key string) {

@ -184,12 +184,11 @@ func (och *OnlineHistoryRedisConsumerHandler) getPushStorageMsgList(
options2 := msgprocessor.Options(msg.Options)
if options2.IsHistory() {
return true
} else {
// if !(!options2.IsSenderSync() && conversationID == msg.MsgData.SendID) {
// return false
// }
return false
}
// if !(!options2.IsSenderSync() && conversationID == msg.MsgData.SendID) {
// return false
// }
return false
}
for _, v := range totalMsgs {
options := msgprocessor.Options(v.message.Options)

@ -90,9 +90,8 @@ func (g *Client) Push(ctx context.Context, userIDs []string, title, content stri
for i, v := range s.GetSplitResult() {
go func(index int, userIDs []string) {
defer wg.Done()
if err := g.batchPush(ctx, token, userIDs, pushReq); err != nil {
if err = g.batchPush(ctx, token, userIDs, pushReq); err != nil {
log.ZError(ctx, "batchPush failed", err, "index", index, "token", token, "req", pushReq)
err = err
}
}(i, v.Item)
}

@ -90,9 +90,8 @@ func (r *pushServer) PushMsg(ctx context.Context, pbData *pbpush.PushMsgReq) (re
if err != nil {
if err != errNoOfflinePusher {
return nil, err
} else {
log.ZWarn(ctx, "offline push failed", err, "msg", pbData.String())
}
log.ZWarn(ctx, "offline push failed", err, "msg", pbData.String())
}
return &pbpush.PushMsgResp{}, nil
}

@ -26,7 +26,6 @@ func GetContent(msg *sdkws.MsgData) string {
_ = proto.Unmarshal(msg.Content, &tips)
content := tips.JsonDetail
return content
} else {
return string(msg.Content)
}
return string(msg.Content)
}

@ -79,9 +79,14 @@ func (s *friendServer) AddBlack(ctx context.Context, req *pbfriend.AddBlackReq)
CreateTime: time.Now(),
Ex: req.Ex,
}
if err := s.blackDatabase.Create(ctx, []*relation.BlackModel{&black}); err != nil {
return nil, err
}
s.notificationSender.BlackAddedNotification(ctx, req)
if err := s.notificationSender.BlackAddedNotification(ctx, req); err != nil {
return nil, err
}
return &pbfriend.AddBlackResp{}, nil
}

@ -114,26 +114,36 @@ func (s *friendServer) ApplyToAddFriend(ctx context.Context, req *pbfriend.Apply
if err := authverify.CheckAccessV3(ctx, req.FromUserID, s.config); err != nil {
return nil, err
}
if req.ToUserID == req.FromUserID {
return nil, errs.ErrCanNotAddYourself.Wrap("req.ToUserID", req.ToUserID)
}
if err = CallbackBeforeAddFriend(ctx, s.config, req); err != nil && err != errs.ErrCallbackContinue {
return nil, err
}
if _, err := s.userRpcClient.GetUsersInfoMap(ctx, []string{req.ToUserID, req.FromUserID}); err != nil {
return nil, err
}
in1, in2, err := s.friendDatabase.CheckIn(ctx, req.FromUserID, req.ToUserID)
if err != nil {
return nil, err
}
if in1 && in2 {
return nil, errs.ErrRelationshipAlready.Wrap()
}
if err = s.friendDatabase.AddFriendRequest(ctx, req.FromUserID, req.ToUserID, req.ReqMsg, req.Ex); err != nil {
return nil, err
}
s.notificationSender.FriendApplicationAddNotification(ctx, req)
if err = s.notificationSender.FriendApplicationAddNotification(ctx, req); err != nil {
return nil, err
}
if err = CallbackAfterAddFriend(ctx, s.config, req); err != nil && err != errs.ErrCallbackContinue {
return nil, err
}
@ -197,7 +207,9 @@ func (s *friendServer) RespondFriendApply(ctx context.Context, req *pbfriend.Res
if err != nil {
return nil, err
}
s.notificationSender.FriendApplicationAgreedNotification(ctx, req)
if err := s.notificationSender.FriendApplicationAgreedNotification(ctx, req); err != nil {
return nil, err
}
return resp, nil
}
if req.HandleResult == constant.FriendResponseRefuse {

@ -33,10 +33,7 @@ func (s *groupServer) GetGroupInfoCache(
return resp, nil
}
func (s *groupServer) GetGroupMemberCache(
ctx context.Context,
req *pbgroup.GetGroupMemberCacheReq,
) (resp *pbgroup.GetGroupMemberCacheResp, err error) {
func (s *groupServer) GetGroupMemberCache(ctx context.Context, req *pbgroup.GetGroupMemberCacheReq) (resp *pbgroup.GetGroupMemberCacheResp, err error) {
members, err := s.db.TakeGroupMember(ctx, req.GroupID, req.GroupMemberID)
if err != nil {
return nil, err

@ -637,6 +637,7 @@ func (s *groupServer) GetGroupMembersInfo(ctx context.Context, req *pbgroup.GetG
return resp, nil
}
// GetGroupApplicationList handles functions that get a list of group requests.
func (s *groupServer) GetGroupApplicationList(ctx context.Context, req *pbgroup.GetGroupApplicationListReq) (*pbgroup.GetGroupApplicationListResp, error) {
groupIDs, err := s.db.FindUserManagedGroupID(ctx, req.FromUserID)
if err != nil {
@ -951,6 +952,7 @@ func (s *groupServer) SetGroupInfo(ctx context.Context, req *pbgroup.SetGroupInf
return nil, errs.Wrap(errs.ErrDismissedAlready)
}
resp := &pbgroup.SetGroupInfoResp{}
count, err := s.db.FindGroupMemberNum(ctx, group.GroupID)
if err != nil {
return nil, err
@ -1077,6 +1079,7 @@ func (s *groupServer) GetGroups(ctx context.Context, req *pbgroup.GetGroupsReq)
total, group, err = s.db.SearchGroup(ctx, req.GroupName, req.Pagination)
resp.Total = uint32(total)
}
if err != nil {
return nil, err
}
@ -1084,10 +1087,12 @@ func (s *groupServer) GetGroups(ctx context.Context, req *pbgroup.GetGroupsReq)
groupIDs := utils.Slice(group, func(e *relationtb.GroupModel) string {
return e.GroupID
})
ownerMembers, err := s.db.FindGroupsOwner(ctx, groupIDs)
if err != nil {
return nil, err
}
ownerMemberMap := utils.SliceToMap(ownerMembers, func(e *relationtb.GroupMemberModel) string {
return e.GroupID
})

@ -156,27 +156,27 @@ func callbackMsgModify(ctx context.Context, globalConfig *config.GlobalConfig, m
return nil
}
func CallbackGroupMsgRead(ctx context.Context, globalConfig *config.GlobalConfig, req *cbapi.CallbackGroupMsgReadReq) error {
if !globalConfig.Callback.CallbackGroupMsgRead.Enable || req.ContentType != constant.Text {
if !globalConfig.Callback.CallbackGroupMsgRead.Enable {
return nil
}
req.CallbackCommand = cbapi.CallbackGroupMsgReadCommand
resp := &cbapi.CallbackGroupMsgReadResp{}
if err := http.CallBackPostReturn(ctx, globalConfig.Callback.CallbackUrl, req, resp, globalConfig.Callback.CallbackMsgModify); err != nil {
if err := http.CallBackPostReturn(ctx, globalConfig.Callback.CallbackUrl, req, resp, globalConfig.Callback.CallbackGroupMsgRead); err != nil {
return err
}
return nil
}
func CallbackSingleMsgRead(ctx context.Context, globalConfig *config.GlobalConfig, req *cbapi.CallbackSingleMsgReadReq) error {
if !globalConfig.Callback.CallbackSingleMsgRead.Enable || req.ContentType != constant.Text {
if !globalConfig.Callback.CallbackSingleMsgRead.Enable {
return nil
}
req.CallbackCommand = cbapi.CallbackSingleMsgRead
resp := &cbapi.CallbackSingleMsgReadResp{}
if err := http.CallBackPostReturn(ctx, globalConfig.Callback.CallbackUrl, req, resp, globalConfig.Callback.CallbackMsgModify); err != nil {
if err := http.CallBackPostReturn(ctx, globalConfig.Callback.CallbackUrl, req, resp, globalConfig.Callback.CallbackSingleMsgRead); err != nil {
return err
}
return nil

@ -137,6 +137,7 @@ func (m *msgServer) SearchMessage(ctx context.Context, req *msg.SearchMessageReq
groupIDs = append(groupIDs, chatLog.GroupID)
}
}
// Retrieve sender and receiver information
if len(sendIDs) != 0 {
sendInfos, err := m.UserLocalCache.GetUsersInfo(ctx, sendIDs)
if err != nil {
@ -155,6 +156,8 @@ func (m *msgServer) SearchMessage(ctx context.Context, req *msg.SearchMessageReq
recvMap[recvInfo.UserID] = recvInfo.Nickname
}
}
// Retrieve group information including member counts
if len(groupIDs) != 0 {
groupInfos, err := m.GroupLocalCache.GetGroupInfos(ctx, groupIDs)
if err != nil {
@ -162,8 +165,14 @@ func (m *msgServer) SearchMessage(ctx context.Context, req *msg.SearchMessageReq
}
for _, groupInfo := range groupInfos {
groupMap[groupInfo.GroupID] = groupInfo
// Get actual member count
memberIDs, err := m.GroupLocalCache.GetGroupMemberIDs(ctx, groupInfo.GroupID)
if err == nil {
groupInfo.MemberCount = uint32(len(memberIDs)) // Update the member count with actual number
}
}
}
// Construct response with updated information
for _, chatLog := range chatLogs {
pbchatLog := &msg.ChatLog{}
utils.CopyStructFields(pbchatLog, chatLog)
@ -175,14 +184,14 @@ func (m *msgServer) SearchMessage(ctx context.Context, req *msg.SearchMessageReq
switch chatLog.SessionType {
case constant.SingleChatType, constant.NotificationChatType:
pbchatLog.RecvNickname = recvMap[chatLog.RecvID]
case constant.GroupChatType, constant.SuperGroupChatType:
pbchatLog.SenderFaceURL = groupMap[chatLog.GroupID].FaceURL
pbchatLog.GroupMemberCount = groupMap[chatLog.GroupID].MemberCount
pbchatLog.RecvID = groupMap[chatLog.GroupID].GroupID
pbchatLog.GroupName = groupMap[chatLog.GroupID].GroupName
pbchatLog.GroupOwner = groupMap[chatLog.GroupID].OwnerUserID
pbchatLog.GroupType = groupMap[chatLog.GroupID].GroupType
groupInfo := groupMap[chatLog.GroupID]
pbchatLog.SenderFaceURL = groupInfo.FaceURL
pbchatLog.GroupMemberCount = groupInfo.MemberCount // Reflects actual member count
pbchatLog.RecvID = groupInfo.GroupID
pbchatLog.GroupName = groupInfo.GroupName
pbchatLog.GroupOwner = groupInfo.OwnerUserID
pbchatLog.GroupType = groupInfo.GroupType
}
resp.ChatLogs = append(resp.ChatLogs, pbchatLog)
}

@ -158,9 +158,6 @@ func (m *msgServer) encapsulateMsgData(msg *sdkws.MsgData) {
case constant.Custom:
fallthrough
case constant.Quote:
utils.SetSwitchFromOptions(msg.Options, constant.IsConversationUpdate, true)
utils.SetSwitchFromOptions(msg.Options, constant.IsUnreadCount, true)
utils.SetSwitchFromOptions(msg.Options, constant.IsSenderSync, true)
case constant.Revoke:
utils.SetSwitchFromOptions(msg.Options, constant.IsUnreadCount, false)
utils.SetSwitchFromOptions(msg.Options, constant.IsOfflinePush, false)

@ -60,6 +60,7 @@ func CheckAdmin(ctx context.Context, config *config.GlobalConfig) error {
}
return errs.ErrNoPermission.Wrap(fmt.Sprintf("user %s is not admin userID", mcontext.GetOpUserID(ctx)))
}
func CheckIMAdmin(ctx context.Context, config *config.GlobalConfig) error {
if utils.IsContain(mcontext.GetOpUserID(ctx), config.IMAdmin.UserID) {
return nil

@ -16,9 +16,9 @@ package mgo
import (
"context"
"github.com/OpenIMSDK/protocol/constant"
"time"
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/mgoutil"
"github.com/OpenIMSDK/tools/pagination"
@ -70,8 +70,12 @@ func (g *GroupMgo) Take(ctx context.Context, groupID string) (group *relation.Gr
}
func (g *GroupMgo) Search(ctx context.Context, keyword string, pagination pagination.Pagination) (total int64, groups []*relation.GroupModel, err error) {
return mgoutil.FindPage[*relation.GroupModel](ctx, g.coll, bson.M{"group_name": bson.M{"$regex": keyword},
"status": bson.M{"$ne": constant.GroupStatusDismissed}}, pagination)
opts := options.Find().SetSort(bson.D{{Key: "created_at", Value: -1}})
return mgoutil.FindPage[*relation.GroupModel](ctx, g.coll, bson.M{
"group_name": bson.M{"$regex": keyword},
"status": bson.M{"$ne": constant.GroupStatusDismissed},
}, pagination, opts)
}
func (g *GroupMgo) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) {

@ -49,11 +49,7 @@ func NewGroupRpcClient(discov discoveryregistry.SvcDiscoveryRegistry, config *co
return GroupRpcClient(*NewGroup(discov, config))
}
func (g *GroupRpcClient) GetGroupInfos(
ctx context.Context,
groupIDs []string,
complete bool,
) ([]*sdkws.GroupInfo, error) {
func (g *GroupRpcClient) GetGroupInfos(ctx context.Context, groupIDs []string, complete bool) ([]*sdkws.GroupInfo, error) {
resp, err := g.Client.GetGroupsInfo(ctx, &group.GetGroupsInfoReq{
GroupIDs: groupIDs,
})
@ -184,11 +180,7 @@ func (g *GroupRpcClient) GetGroupInfoCache(ctx context.Context, groupID string)
return resp.GroupInfo, nil
}
func (g *GroupRpcClient) GetGroupMemberCache(
ctx context.Context,
groupID string,
groupMemberID string,
) (*sdkws.GroupMemberFullInfo, error) {
func (g *GroupRpcClient) GetGroupMemberCache(ctx context.Context, groupID string, groupMemberID string) (*sdkws.GroupMemberFullInfo, error) {
resp, err := g.Client.GetGroupMemberCache(ctx, &group.GetGroupMemberCacheReq{
GroupID: groupID,
GroupMemberID: groupMemberID,

@ -126,10 +126,7 @@ func (f *FriendNotificationSender) UserInfoUpdatedNotification(ctx context.Conte
return f.Notification(ctx, mcontext.GetOpUserID(ctx), changedUserID, constant.UserInfoUpdatedNotification, &tips)
}
func (f *FriendNotificationSender) FriendApplicationAddNotification(
ctx context.Context,
req *pbfriend.ApplyToAddFriendReq,
) error {
func (f *FriendNotificationSender) FriendApplicationAddNotification(ctx context.Context, req *pbfriend.ApplyToAddFriendReq) error {
tips := sdkws.FriendApplicationTips{FromToUserID: &sdkws.FromToUserID{
FromUserID: req.FromUserID,
ToUserID: req.ToUserID,

@ -932,7 +932,7 @@ openim::test::set_group_info() {
{
"groupInfoForSet": {
"groupID": "${1}",
"groupName": "new-name",
"groupName": "new group name",
"notification": "new notification",
"introduction": "new introduction",
"faceURL": "www.newfaceURL.com",
@ -1076,6 +1076,7 @@ function openim::test::group() {
local GROUP_ID=$RANDOM
local GROUP_ID2=$RANDOM
# Assumes that TEST_GROUP_ID, USER_ID, and other necessary IDs are set as environment variables before running this suite.
# 0. Register a friend user.
openim::test::user_register "${USER_ID}" "group00" "new_face_url"

@ -413,7 +413,7 @@ openim::util::check_process_names() {
else
# If there are PIDs, loop through each one
for pid in "${pids[@]}"; do
local command=$(ps -p $pid -o cmd=)
local command=$(ps -p $pid -o comm=)
local start_time=$(ps -p $pid -o lstart=)
local port=$(get_port $pid)
@ -489,7 +489,7 @@ openim::util::check_process_names_for_stop() {
else
# If there are PIDs, loop through each one
for pid in "${pids[@]}"; do
local command=$(ps -p $pid -o cmd=)
local command=$(ps -p $pid -o comm=)
local start_time=$(ps -p $pid -o lstart=)
local port=$(get_port $pid)

@ -1,46 +0,0 @@
#!/usr/bin/env bash
# Copyright © 2023 OpenIM. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This script verifies whether codes follow golang convention.
# Usage: `scripts/verify-pkg-names.sh`.
set -o errexit
OPENIM_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
source "${OPENIM_ROOT}/scripts/lib/init.sh"
openim::golang::verify_go_version
openim::golang::verify_go_version
OPENIM_OUTPUT_HOSTBIN_TOOLS="${OPENIM_ROOT}/_output/bin/tools/linux/amd64"
CODESCAN_BINARY="${OPENIM_OUTPUT_HOSTBIN_TOOLS}/codescan"
if [[ ! -f "${CODESCAN_BINARY}" ]]; then
echo "codescan binary not found, building..."
pushd "${OPENIM_ROOT}" >/dev/null
make build BINS="codescan"
popd >/dev/null
fi
if [[ ! -f "${CODESCAN_BINARY}" ]]; then
echo "Failed to build codescan binary."
exit 1
fi
CONFIG_PATH="${OPENIM_ROOT}/tools/codescan/config.yaml"
"${CODESCAN_BINARY}" -config "${CONFIG_PATH}"

@ -1,104 +0,0 @@
// Copyright © 2024 OpenIM. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package checker
import (
"bufio"
"fmt"
"os"
"path/filepath"
"regexp"
"strings"
"github.com/openimsdk/open-im-server/tools/codescan/config"
)
type CheckResult struct {
FilePath string
Lines []int
}
func checkFileForChineseComments(filePath string) ([]CheckResult, error) {
file, err := os.Open(filePath)
if err != nil {
return nil, err
}
defer file.Close()
var results []CheckResult
scanner := bufio.NewScanner(file)
reg := regexp.MustCompile(`[\p{Han}]+`)
lineNumber := 0
var linesWithChinese []int
for scanner.Scan() {
lineNumber++
if reg.FindString(scanner.Text()) != "" {
linesWithChinese = append(linesWithChinese, lineNumber)
}
}
if len(linesWithChinese) > 0 {
results = append(results, CheckResult{
FilePath: filePath,
Lines: linesWithChinese,
})
}
if err := scanner.Err(); err != nil {
return nil, err
}
return results, nil
}
func WalkDirAndCheckComments(cfg config.Config) error {
var allResults []CheckResult
err := filepath.Walk(cfg.Directory, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
for _, fileType := range cfg.FileTypes {
if filepath.Ext(path) == fileType {
results, err := checkFileForChineseComments(path)
if err != nil {
return err
}
if len(results) > 0 {
allResults = append(allResults, results...)
}
}
}
return nil
})
if err != nil {
return err
}
if len(allResults) > 0 {
var errMsg strings.Builder
errMsg.WriteString("Files containing Chinese comments:\n")
for _, result := range allResults {
errMsg.WriteString(fmt.Sprintf("%s: Lines %v\n", result.FilePath, result.Lines))
}
return fmt.Errorf(errMsg.String())
}
return nil
}

@ -1,34 +0,0 @@
// Copyright © 2024 OpenIM. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main
import (
"log"
"github.com/openimsdk/open-im-server/tools/codescan/checker"
"github.com/openimsdk/open-im-server/tools/codescan/config"
)
func main() {
cfg, err := config.ParseConfig()
if err != nil {
log.Fatalf("Error parsing config: %v", err)
}
err = checker.WalkDirAndCheckComments(cfg)
if err != nil {
panic(err)
}
}

@ -1,49 +0,0 @@
// Copyright © 2024 OpenIM. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package config
import (
"flag"
"log"
"os"
"gopkg.in/yaml.v2"
)
type Config struct {
Directory string `yaml:"directory"`
FileTypes []string `yaml:"file_types"`
Languages []string `yaml:"languages"`
}
func ParseConfig() (Config, error) {
var configPath string
flag.StringVar(&configPath, "config", "./", "Path to config file")
flag.Parse()
var config Config
if configPath != "" {
configFile, err := os.ReadFile(configPath)
if err != nil {
return Config{}, err
}
if err := yaml.Unmarshal(configFile, &config); err != nil {
return Config{}, err
}
} else {
log.Fatal("Config file must be provided")
}
return config, nil
}

@ -1,3 +0,0 @@
module github.com/openimsdk/open-im-server/tools/codescan
go 1.19
Loading…
Cancel
Save