Skip to content

Commit

Permalink
feat: add throttle limit notification
Browse files Browse the repository at this point in the history
  • Loading branch information
weaigc committed Jul 24, 2023
1 parent e1a1c7c commit 52ca67f
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 13 deletions.
1 change: 0 additions & 1 deletion src/components/chat-message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ export function ChatMessage({ message, ...props }: ChatMessageProps) {
remarkPlugins={[remarkGfm, remarkMath, supersub, remarkBreaks]}
components={{
img(obj) {
console.log(obj)
try {
const uri = new URL(obj.src!)
const w = uri.searchParams.get('w')
Expand Down
20 changes: 14 additions & 6 deletions src/components/chat-notification.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ export interface ChatNotificationProps extends Pick<ReturnType<typeof useBing>,
}

function getAction(error: ChatError, reset: () => void) {
if (error.code === ErrorCode.THROTTLE_LIMIT) {
reset()
return (
<div>
你已达到每日最大发送消息次数,请<a href={`#dialog="settings"`}>更换账号</a>或隔一天后重试
</div>
)
}
if (error.code === ErrorCode.BING_FORBIDDEN) {
return (
<ExternalLink href="https://bing.com/new">
Expand Down Expand Up @@ -55,15 +63,15 @@ export function ChatNotification({ message, bot }: ChatNotificationProps) {
className="notification-container"
>
<div className="bottom-notifications">
<div className="inline-type with-decorative-line">
<div className="text-container mt-1">
<div className="title inline-flex items-start">
<Image alt="error" src={IconWarning} width={20} className="mr-1 mt-1" />
{getAction(message.error, () => bot.resetConversation())}
<div className="inline-type with-decorative-line">
<div className="text-container mt-1">
<div className="title inline-flex items-start">
<Image alt="error" src={IconWarning} width={20} className="mr-1 mt-1" />
{getAction(message.error, () => bot.resetConversation())}
</div>
</div>
</div>
</div>
</div>
</div>
)
}
6 changes: 3 additions & 3 deletions src/lib/bots/bing/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -314,9 +314,9 @@ export class BingWebBot {
type: 'ERROR',
error: new ChatError(
event.item.result.error || 'Unknown error',
event.item.result.value !== 'CaptchaChallenge' ? ErrorCode.UNKOWN_ERROR
: this.conversationContext?.conversationId?.includes('BingProdUnAuthenticatedUsers') ? ErrorCode.BING_UNAUTHORIZED
: ErrorCode.BING_CAPTCHA ,
event.item.result.value === 'Throttled' ? ErrorCode.THROTTLE_LIMIT
: event.item.result.value === 'CaptchaChallenge' ? (this.conversationContext?.conversationId?.includes('BingProdUnAuthenticatedUsers') ? ErrorCode.BING_UNAUTHORIZED : ErrorCode.BING_CAPTCHA)
: ErrorCode.UNKOWN_ERROR
),
})
return
Expand Down
70 changes: 70 additions & 0 deletions src/lib/bots/bing/speak.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { sleep } from './utils'

const synth = window.speechSynthesis

export class Speaker {
lastIndex = 0
lastText = ''
private controller = new AbortController()
private speaking = false
finished = false
constructor() {}
abort() {
this.controller.abort()
}

reset() {
this.speaking = false
this.finished = true
this.abort()
}

speak(text: string) {
if (!synth || text?.trim()?.length < 2) {
return
}
this.lastText = text.replace(/[^\u4e00-\u9fa5_a-zA-Z0-9,。?,:\.,:]+/g, '')
this.finished = false
this.loop()
}

private async doSpeek() {
return new Promise((resolve) => {
const currentIndex = Math.max(this.lastText.indexOf('。'), this.lastText.indexOf('?'), this.lastText.length, this.lastIndex)
if (currentIndex === this.lastIndex) {
return
}
const text = this.lastText.slice(this.lastIndex, currentIndex)
this.lastIndex = currentIndex
const utterThis = new SpeechSynthesisUtterance(text)
this.controller.signal.onabort = () => {
synth.cancel()
this.finished = true
resolve(false)
}

utterThis.onend = function (event) {
console.log("SpeechSynthesisUtterance.onend")
resolve(true)
}

utterThis.onerror = function (event) {
console.error("SpeechSynthesisUtterance.onerror")
resolve(false)
}
const voice = synth.getVoices().find(v => v.name.includes('Microsoft Yunxi Online')) ?? null
utterThis.voice = voice
synth.speak(utterThis)
})
}

private async loop() {
if (this.speaking) return
this.speaking = true
while(!this.finished) {
await this.doSpeek()
await sleep(800)
}
this.speaking = false
}
}
1 change: 1 addition & 0 deletions src/lib/bots/bing/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export enum ErrorCode {
BING_UNAUTHORIZED = 'BING_UNAUTHORIZED',
BING_FORBIDDEN = 'BING_FORBIDDEN',
BING_CAPTCHA = 'BING_CAPTCHA',
THROTTLE_LIMIT = 'THROTTLE_LIMIT',
NOTFOUND_ERROR = 'NOT_FOUND_ERROR',
UNKOWN_ERROR = 'UNKOWN_ERROR',
NETWORK_ERROR = 'NETWORK_ERROR',
Expand Down
6 changes: 3 additions & 3 deletions src/lib/hooks/use-bing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ export function useBing(botId: BotId = 'bing') {
if (event.data.text.length > message.text.length) {
message.text = event.data.text
}
if (event.data.spokenText) {
speaker.speak(event.data.spokenText)
}
// if (event.data.spokenText) {
// speaker.speak(event.data.spokenText)
// }

message.throttling = event.data.throttling || message.throttling
message.sourceAttributions = event.data.sourceAttributions || message.sourceAttributions
Expand Down

0 comments on commit 52ca67f

Please sign in to comment.