fix: fix sharing message use message action issue

This commit is contained in:
Zhang Minghan 2024-03-11 20:09:34 +08:00
parent a5d2c8c1ff
commit f7a135af0e
6 changed files with 51 additions and 38 deletions

View File

@ -41,6 +41,7 @@ type MessageProps = {
index: number;
message: Message;
end?: boolean;
username?: string;
onEvent?: (event: string, index?: number, message?: string) => void;
ref?: Ref<HTMLElement>;
sharing?: boolean;
@ -216,10 +217,11 @@ function MessageContent({
index,
onEvent,
selected,
username,
}: MessageProps) {
const isUser = message.role === "user";
const username = useSelector(selectUsername);
const user = useSelector(selectUsername);
const [open, setOpen] = useState(false);
const [editedMessage, setEditedMessage] = useState<string | undefined>("");
@ -239,7 +241,7 @@ function MessageContent({
isUser ? (
<Avatar
className={`message-avatar animate-fade-in`}
username={username}
username={username ?? user}
/>
) : (
<img

View File

@ -1,12 +0,0 @@
import { EventCommitter } from "./struct.ts";
import { Message } from "@/api/types.tsx";
export type SharingEvent = {
refer: string;
data: Message[];
};
export const sharingEvent = new EventCommitter<SharingEvent>({
name: "sharing",
destroyedAfterTrigger: true,
});

View File

@ -19,7 +19,6 @@ import MessageSegment from "@/components/Message.tsx";
import { Button } from "@/components/ui/button.tsx";
import router from "@/router.tsx";
import { useToast } from "@/components/ui/use-toast.ts";
import { sharingEvent } from "@/events/sharing.ts";
import { Message } from "@/api/types.tsx";
import Avatar from "@/components/Avatar.tsx";
import { toJpeg } from "html-to-image";
@ -28,18 +27,20 @@ import { extractMessage } from "@/utils/processor.ts";
import { cn } from "@/components/ui/lib/utils.ts";
import { useMobile } from "@/utils/device.ts";
import { ScrollArea } from "@/components/ui/scroll-area.tsx";
import { useConversationActions } from "@/store/chat.ts";
type SharingFormProps = {
refer?: string;
data: ViewData | null;
};
function SharingForm({ refer, data }: SharingFormProps) {
function SharingForm({ data }: SharingFormProps) {
if (data === null) return null;
const { t } = useTranslation();
const { toast } = useToast();
const mobile = useMobile();
const { mask: setMask } = useConversationActions();
const [maximized, setMaximized] = useState(false);
const container = useRef<HTMLDivElement>(null);
const date = new Date(data.time);
@ -111,7 +112,12 @@ function SharingForm({ refer, data }: SharingFormProps) {
</div>
<div className={`shot-content`}>
{data.messages.map((message, i) => (
<MessageSegment message={message} key={i} index={i} />
<MessageSegment
message={message}
key={i}
index={i}
username={data.username}
/>
))}
</div>
</div>
@ -151,9 +157,11 @@ function SharingForm({ refer, data }: SharingFormProps) {
<Button
variant={`outline`}
onClick={async () => {
sharingEvent.emit({
refer: refer as string,
data: data?.messages as Message[],
const message: Message[] = data?.messages || [];
setMask({
avatar: "",
name: data.name,
context: message,
});
await router.navigate("/");
}}

View File

@ -14,10 +14,10 @@ type Limiter struct {
Count int64
}
func (l *Limiter) RateLimit(client *redis.Client, ip string, path string) bool {
func (l *Limiter) RateLimit(client *redis.Client, ip string, path string) (bool, error) {
key := fmt.Sprintf("rate:%s:%s", path, ip)
rate := utils.IncrWithLimit(client, key, 1, l.Count, int64(l.Duration))
return !rate
rate, err := utils.IncrWithLimit(client, key, 1, l.Count, int64(l.Duration))
return !rate, err
}
var limits = map[string]Limiter{
@ -64,14 +64,28 @@ func ThrottleMiddleware() gin.HandlerFunc {
cache := utils.GetCacheFromContext(c)
limiter := GetPrefixMap[Limiter](path, limits)
if limiter != nil && limiter.RateLimit(cache, ip, path) {
c.JSON(200, gin.H{
"status": false,
"reason": "You have sent too many requests. Please try again later.",
"error": "request_throttled",
})
c.Abort()
return
if limiter != nil {
rate, err := limiter.RateLimit(cache, ip, path)
if err != nil {
c.JSON(200, gin.H{
"status": false,
"reason": err.Error(),
"error": err.Error(),
})
c.Abort()
return
}
if rate {
c.JSON(200, gin.H{
"status": false,
"reason": "You have sent too many requests. Please try again later.",
"error": "request_throttled",
})
c.Abort()
return
}
}
c.Next()
}

View File

@ -53,25 +53,25 @@ func SetCache(cache *redis.Client, key string, value string, expiration int64) e
return cache.Set(context.Background(), key, value, time.Duration(expiration)*time.Second).Err()
}
func IncrWithLimit(cache *redis.Client, key string, delta int64, limit int64, expiration int64) bool {
func IncrWithLimit(cache *redis.Client, key string, delta int64, limit int64, expiration int64) (bool, error) {
// not exist
if _, err := cache.Get(context.Background(), key).Result(); err != nil {
if errors.Is(err, redis.Nil) {
cache.Set(context.Background(), key, delta, time.Duration(expiration)*time.Second)
return true
return true, nil
}
return false
return false, err
}
res, err := Incr(cache, key, delta)
if err != nil {
return false
return false, err
}
if res > limit {
// reset
cache.Set(context.Background(), key, limit, time.Duration(expiration)*time.Second)
return false
return false, nil
}
return true
return true, nil
}
func DecrInt(cache *redis.Client, key string, delta int64) bool {

View File

@ -145,7 +145,8 @@ func (w *WebSocket) IncrRate(key string) bool {
func (w *WebSocket) IncrRateWithLimit(key string, limit int64, expiration int64) bool {
cache := w.GetCache()
return IncrWithLimit(cache, key, 1, limit, expiration)
state, err := IncrWithLimit(cache, key, 1, limit, expiration)
return state && err == nil
}
func (w *WebSocket) GetCtx() *gin.Context {