2024-04-07 19:41:19 -06:00
import logging
import time
import traceback
from nio import RoomMessageText , MatrixRoom , MegolmEvent , InviteMemberEvent , JoinError
from matrix_gpt import MatrixClientHelper
2024-04-07 22:27:00 -06:00
from matrix_gpt . api_client_manager import api_client_helper
2024-04-07 19:41:19 -06:00
from matrix_gpt . chat_functions import is_this_our_thread , get_thread_content , check_command_prefix , check_authorized
from matrix_gpt . config import global_config
from matrix_gpt . generate import generate_ai_response
2024-04-07 22:27:00 -06:00
from matrix_gpt . generate_clients . command_info import CommandInfo
2024-04-07 19:41:19 -06:00
2024-04-07 22:27:00 -06:00
logger = logging . getLogger ( ' MatrixGPT ' ) . getChild ( ' HandleActions ' )
2024-04-07 19:41:19 -06:00
2024-04-07 22:27:00 -06:00
async def do_reply_msg ( client_helper : MatrixClientHelper , room : MatrixRoom , requestor_event : RoomMessageText , command_info : CommandInfo , command_activated : bool ) :
2024-04-07 19:41:19 -06:00
try :
raw_msg = requestor_event . body . strip ( ) . strip ( ' \n ' )
2024-04-07 22:27:00 -06:00
msg = raw_msg if not command_activated else raw_msg [ len ( command_info . trigger ) : ] . strip ( ) # Remove the command prefix
2024-04-07 19:41:19 -06:00
await generate_ai_response (
client_helper = client_helper ,
room = room ,
event = requestor_event ,
msg = msg ,
2024-04-07 22:27:00 -06:00
command_info = command_info ,
2024-04-07 19:41:19 -06:00
)
except Exception :
logger . critical ( traceback . format_exc ( ) )
await client_helper . react_to_event ( room . room_id , requestor_event . event_id , ' ❌ ' )
raise
2024-04-07 22:27:00 -06:00
async def do_reply_threaded_msg ( client_helper : MatrixClientHelper , room : MatrixRoom , requestor_event : RoomMessageText ) :
2024-04-07 19:41:19 -06:00
client = client_helper . client
is_our_thread , sent_command_prefix , command_info = await is_this_our_thread ( client , room , requestor_event )
if not is_our_thread : # or room.member_count == 2
return
2024-04-07 22:27:00 -06:00
if not check_authorized ( requestor_event . sender , command_info . allowed_to_chat ) :
await client_helper . react_to_event ( room . room_id , requestor_event . event_id , ' 🚫 ' , extra_error = ' Not allowed to chat. ' if global_config [ ' send_extra_messages ' ] else None )
return
if not check_authorized ( requestor_event . sender , command_info . allowed_to_thread ) :
await client_helper . react_to_event ( room . room_id , requestor_event . event_id , ' 🚫 ' , extra_error = ' Not allowed to thread. ' if global_config [ ' send_extra_messages ' ] else None )
2024-04-07 19:41:19 -06:00
return
try :
# TODO: sync this with redis so that we don't clear the typing state if another response is also processing
await client . room_typing ( room . room_id , typing_state = True , timeout = 30000 )
thread_content = await get_thread_content ( client , room , requestor_event )
2024-04-07 22:27:00 -06:00
api_client = api_client_helper . get_client ( command_info . api_type )
2024-04-07 19:41:19 -06:00
for event in thread_content :
if isinstance ( event , MegolmEvent ) :
await client_helper . send_text_to_room (
room . room_id ,
' ❌ 🔐 Decryption Failure ' ,
reply_to_event_id = event . event_id ,
thread = True ,
thread_root_id = thread_content [ 0 ] . event_id
)
logger . critical ( f ' Decryption failure for event { event . event_id } in room { room . room_id } ' )
await client . room_typing ( room . room_id , typing_state = False , timeout = 1000 )
return
else :
thread_msg = event . body . strip ( ) . strip ( ' \n ' )
2024-04-07 22:27:00 -06:00
api_client . append_msg (
role = api_client . BOT_NAME if event . sender == client . user_id else api_client . HUMAN_NAME ,
content = thread_msg if not check_command_prefix ( thread_msg ) [ 0 ] else thread_msg [ len ( sent_command_prefix ) : ] . strip ( )
2024-04-07 19:41:19 -06:00
)
await generate_ai_response (
client_helper = client_helper ,
room = room ,
event = requestor_event ,
2024-04-07 22:27:00 -06:00
msg = api_client . context ,
command_info = command_info ,
2024-04-07 19:41:19 -06:00
thread_root_id = thread_content [ 0 ] . event_id
)
except :
2024-04-07 22:27:00 -06:00
logger . error ( traceback . format_exc ( ) )
2024-04-07 19:41:19 -06:00
await client_helper . react_to_event ( room . room_id , event . event_id , ' ❌ ' )
raise
async def do_join_channel ( client_helper : MatrixClientHelper , room : MatrixRoom , event : InviteMemberEvent ) :
2024-04-07 22:27:00 -06:00
if not check_authorized ( event . sender , global_config [ ' allowed_to_invite ' ] ) and room . room_id not in global_config [ ' blacklist_rooms ' ] :
2024-04-07 19:41:19 -06:00
logger . info ( f ' Got invite to { room . room_id } from { event . sender } but rejected ' )
return
2024-04-07 22:27:00 -06:00
# Attempt to join 3 times before giving up.
2024-04-07 19:41:19 -06:00
client = client_helper . client
for attempt in range ( 3 ) :
result = await client . join ( room . room_id )
if isinstance ( result , JoinError ) :
logger . error ( f ' Error joining room { room . room_id } (attempt { attempt } ): " { result . message } " ' )
time . sleep ( 5 )
else :
logger . info ( f ' Joined via invite: { room . room_id } ' )
return
else :
logger . error ( f ' Unable to join room: { room . room_id } ' )
2024-04-07 22:44:27 -06:00
async def sound_off ( room : MatrixRoom , event : RoomMessageText , client_helper : MatrixClientHelper ) :
text_response = """ ## MatrixGPT
< https : / / git . evulid . cc / cyberes / MatrixGPT >
### Commands
` ! matrixgpt ` - show this help message \n \n """
for command in global_config [ ' command ' ] :
text_response = text_response + f " ` { command [ ' trigger ' ] } ` - Model: { command [ ' model ' ] } . Temperature: { command [ ' temperature ' ] } . Max tokens: { command [ ' max_tokens ' ] } . \n \n "
return await client_helper . send_text_to_room (
room . room_id ,
text_response ,
reply_to_event_id = event . event_id ,
markdown_convert = True
)