Sie können hier spenden, wenn Sie dies weiterentwickeln möchten: https://www.buymaacoffee.com/prxm
Eine vollständig vorgestellte, ereignisgesteuerte Chatbot-Bibliothek für Reddit-Chatrooms!
Funktioniert entweder mit Reddit -Benutzername und Passwort oder dem API -Token (nicht regelmäßig, die Sie von Ihrer registrierten App erhalten, da es nicht vollständig geschrieben ist)
pip install Reddit-ChatBot-Python
erforderlich:
websocket_client
requests
Das Modul ist multithread und ereignisorientiert. Sie kümmern sich um das, was bei diesen Ereignissen passieren wird, indem Sie Ihre Funktion mit dem Dekorateur des entsprechenden Ereignisses schreiben.
Zum Erstellen einer Instanz von RedditAuthenticaton gibt es zwei Optionen
Empfohlener Weg ist das Erstellen einer PasswortAuth:
from Reddit_ChatBot_Python import RedditAuthentication
reddit_authentication = RedditAuthentication . PasswordAuth ( reddit_username = "" ,
reddit_password = "" ,
twofa = None )Oder Sie können mit Ihrem selbstbezogenen API-Schlüssel gehen. (Nicht die, die Sie von Ihrer registrierten App erhalten)
from Reddit_ChatBot_Python import RedditAuthentication
reddit_authentication = RedditAuthentication . TokenAuth ( token = "" )dann den Chatbot mit dem übergebenen Reddit_authentication instanziiert
from Reddit_ChatBot_Python import ChatBot
chatbot = ChatBot ( print_chat = True ,
store_session = True ,
log_websocket_frames = False ,
authentication = reddit_authentication
) print_chat druckt das print der Chat -Nachrichten auf der Konsole
store_session , wenn auf True festgelegt wird, erstellt eine Sitzungsdatei, in der die Reddit_authentication in demselben Verzeichnis speichert, in dem das Hauptskript aufgerufen wurde. Beschleunigt die Initalverbindung.
log_websocket_frames protokolliert die nicht überhelmten WebSocket-Frames auf der Konsole
authentication ist die RedditAuthentication die Sie zuvor instanziiert haben
Die Ereignisse:
@ chatbot . event . on_messageDer Ereignis einer regulären Chat -Nachricht.
@ chatbot . event . on_readyDas Ereignis der Verbindung zu den Chats zum ersten Mal. Nur einmal ausgeführt.
@ chatbot . event . on_invitationDer Ereignis des Bot, der eine Chat -Einladung auffordert, unabhängig davon, ob es direkt oder Gruppe ist.
@ chatbot . event . on_invitation_of_otherDer Ereignis eines anderen Benutzers, der eine Einladung für einen Gruppenchat auffordert, in dem sich der Bot befindet.
@ chatbot . event . on_message_deletedDer Ereignis eines Benutzers, der seine Nachricht löscht.
@ chatbot . event . on_user_joinedDer Ereignis eines Benutzers, der zu einem Chat ist, in dem sich der Bot befindet.
@ chatbot . event . on_user_leftDer Ereignis eines Benutzers, in dem der Bot einen Chat verlässt.
@ chatbot . event . on_user_typingDas Ereignis einer Benutzer -Eingabe.
@ chatbot . event . on_user_readDer Ereignis eines Benutzers, der eine Nachricht liest.
@ chatbot . event . on_broadcastDer Ereignis des Empfangens einer Sendung wie beim User Join
@ chatbot . event . on_reactionDer Ereignis eines Benutzers, der eine Reaktion sendet
Alle Ereignisse erhalten als Argument einen analysierten Rahmen. Sie werden so behandelt .:
@ chatbot . event . on_message
def greet ( resp ):
if resp . user . name == chatbot . get_own_name (): # return if the message is from the bot
return True
if resp . message == "Hi!" :
chatbot . send_message ( "Hello!" , resp . channel_url )
return True True von Ereignissen bedeutet, dass die Behandlung der anderen Ereignisse nicht durchgeführt wird!
resp.channel_url ist die URL des Kanals, an die wir die Nachricht senden möchten (resp.Channel_url In diesem Fall der Kanal, in dem die "Hi!" -Smeldung gesendet wurde.)
Das Argument resp enthält mehr Daten als nur den Benutzer und die Nachrichtenzeichenfolge. Die Instanzen von Resp für einige Ereignisse sind unten aufgeführt.
Alles, was noch übrig ist, ist der Chatbot:
chatbot . run_4ever ( auto_reconnect = True )Wie auf die auf Felder zugegriffen werden:
message = resp.message
nickname = resp.user.name
{
"msg_id" : 1000000 ,
"is_op_msg" : false ,
"is_guest_msg" : true ,
"message" : " msg " ,
"silent" : false ,
"ts" : 1611782454265 ,
"channel_url" : " sendbird_group_channel_000000000_0000000000000000000000000000000000000000 " ,
"is_removed" : false ,
"sts" : 1611782454265 ,
"user" : {
"is_blocked_by_me" : false ,
"require_auth_for_profile_image" : false ,
"name" : " *user nickname* " ,
"is_bot" : false ,
"image" : " " ,
"is_active" : true ,
"guest_id" : " t2_5z9rqylm " ,
"friend_discovery_key" : null ,
"role" : " " ,
"friend_name" : null ,
"id" : 10000
}
}{
"unread_cnt" : {
"all" : 1 ,
"ts" : 1614006345986
},
"is_super" : false ,
"data" : {
"inviter" : {
"nickname" : " *inviter nickname* " ,
"metadata" : {
},
"require_auth_for_profile_image" : false ,
"profile_url" : " " ,
"user_id" : " *user id str t2_ included* "
},
"invited_at" : 1614006345956 ,
"invitees" : [
{
"nickname" : " *bot's nickname* " ,
"metadata" : {
},
"require_auth_for_profile_image" : false ,
"profile_url" : " " ,
"user_id" : " t2_5z9rqylm "
}
]
},
"ts" : 1614006345978 ,
"is_access_code_required" : false ,
"cat" : 10020 ,
"channel_type" : " *can either be 'group' for group chat or 'direct' for DM* " ,
"channel_id" : 177639012 ,
"sts" : 1614006345978 ,
"channel_url" : " sendbird_group_channel_000000000_0000000000000000000000000000000000000000 "
}{
"is_super" : false ,
"data" : {
"is_bulk" : true ,
"users" : [
{
"require_auth_for_profile_image" : false ,
"nickname" : " nickname " ,
"role" : " " ,
"user_id" : " t2_5z9rqylm " ,
"inviter" : {
"user_id" : " t2_5z9rqylm " ,
"role" : " " ,
"require_auth_for_profile_image" : false ,
"nickname" : " nickname " ,
"profile_url" : " " ,
"metadata" : {
}
},
"profile_url" : " " ,
"metadata" : {
}
}
]
},
"ts" : 1614264797294 ,
"is_access_code_required" : false ,
"cat" : 10000 ,
"channel_type" : " group " ,
"channel_id" : 177639012 ,
"sts" : 1614264797294 ,
"channel_url" : " sendbird_group_channel_000000000_0000000000000000000000000000000000000000 "
}{
"channel_type" : " group " ,
"channel_id" : 177639012 ,
"is_super" : false ,
"channel" : {
"custom_type" : " group " ,
"is_ephemeral" : false ,
"freeze" : false ,
"disappearing_message" : {
"message_survival_seconds" : -1 ,
"is_triggered_by_message_read" : false
},
"member_count" : 2 ,
"is_broadcast" : false ,
"last_message" : null ,
"unread_mention_count" : 0 ,
"sms_fallback" : {
"wait_seconds" : -1 ,
"exclude_user_ids" : [
]
},
"is_discoverable" : false ,
"ignore_profanity_filter" : false ,
"channel_url" : " sendbird_group_channel_000000000_0000000000000000000000000000000000000000 " ,
"message_survival_seconds" : -1 ,
"unread_message_count" : 0 ,
"is_distinct" : false ,
"cover_url" : " https: // static.sendbird.com / sample / cover / cover_00.jpg " ,
"members" : [
{
"is_active" : true ,
"state" : " " ,
"user_id" : 10000000 ,
"is_online" : false ,
"is_muted" : false ,
"require_auth_for_profile_image" : false ,
"last_seen_at" : 0 ,
"nickname" : " nickname1 " ,
"profile_url" : " " ,
"metadata" : {
}
},
{
"is_active" : true ,
"state" : " " ,
"user_id" : 10000000 ,
"is_online" : false ,
"is_muted" : false ,
"require_auth_for_profile_image" : false ,
"last_seen_at" : 0 ,
"nickname" : " nickname2 " ,
"profile_url" : " " ,
"metadata" : {
}
}
],
"is_public" : false ,
"data" : " " ,
"joined_member_count" : 1 ,
"is_super" : false ,
"name" : " group name " ,
"created_at" : 1614264775 ,
"is_access_code_required" : false ,
"max_length_message" : 5000
},
"sts" : 1614265517558 ,
"channel_url" : " sendbird_group_channel_000000000_0000000000000000000000000000000000000000 " ,
"data" : {
"require_auth_for_profile_image" : false ,
"member_count" : 2 ,
"user_id" : " t2_5z9rqylm " ,
"joined_member_count" : 1 ,
"nickname" : " nickanme of user who left the group " ,
"profile_url" : " " ,
"metadata" : {
}
},
"ts" : 1614265517558 ,
"is_access_code_required" : false ,
"cat" : 10001
}{
"is_super" : false ,
"msg_id" : 2323966291 ,
"ts" : 1614266924885 ,
"channel_type" : " group " ,
"channel_id" : 177623421 ,
"sts" : 1614266924885 ,
"channel_url" : " sendbird_group_channel_000000000_0000000000000000000000000000000000000000 "
}{
"is_super" : false ,
"data" : {
"require_auth_for_profile_image" : false ,
"user_id" : " t2_xxxxxx " ,
"nickname" : " xxxx " ,
"profile_url" : " " ,
"metadata" : {
}
},
"ts" : 1617897296948 ,
"is_access_code_required" : false ,
"cat" : 10900 ,
"channel_type" : " group " ,
"channel_id" : 11111111 ,
"sts" : 1617897296948 ,
"channel_url" : " sendbird_group_channel_000000000_0000000000000000000000000000000000000000 "
} from Reddit_ChatBot_Python import ChatBot , RedditAuthentication
from Reddit_ChatBot_Python import CustomType , Snoo , Reaction
import random # for a basic dice rolling game
# create authentication with username and pass
reddit_authentication = RedditAuthentication . PasswordAuth ( reddit_username = "" , reddit_password = "" ,
twofa = None ) # 2FA supported, default'd to None
# instantiate the chatbot
chatbot = ChatBot ( print_chat = True , store_session = True , log_websocket_frames = False , # some parameters u might wanna know
authentication = reddit_authentication )
# you can add a rate limit like so:
chatbot . enable_rate_limiter ( max_calls = 23 , # how many messages will be sent by the bot
period = 1.5 # in what period (minutes)
)
# now you can add hooks which will be executed when a frame is received like so:
@ chatbot . event . on_message
def dice_roller ( resp ): # resp is a SimpleNamespace that carries all the data of the received frame
messg_s = resp . message . split ()
if messg_s [ 0 ] == "!roll" and len ( messg_s ) == 3 : # if received message says !roll
chatbot . send_reaction ( Reaction . REACT4 , resp . msg_id , resp . channel_url ) # send a reaction
limit_bottom = int ( messg_s [ 1 ])
limit_top = int ( messg_s [ 2 ])
rolled_number = random . randint ( limit_bottom , limit_top )
response_text = f"@ { resp . user . name } rolled { rolled_number } . Better luck next time!"
# send typing indicator cuz why not? maybe they think you are a real person
chatbot . send_typing_indicator ( resp . channel_url )
chatbot . send_message ( response_text ,
resp . channel_url ) # send the message, always add resp.channel_url as the second argument
chatbot . stop_typing_indicator ( resp . channel_url )
chatbot . send_snoomoji ( Snoo . PARTYPARROT , resp . channel_url ) # and send a snoomoji cuz why not??
return True # return true if you want to be done with checking the other hooks, otherwise return None or False
# keep in mind that first added hooks get executed first
# now everytime someone says "!roll 1 100", the bot will roll a dice between 1 and 100 and send the result!
# there are also host actions availabe but ofc they require the bot account to be the host of the chatroom
@ chatbot . event . on_message
def keeper_of_decency ( resp ):
if resp . message == "*some very bad slur word*" :
chatbot . kick_user ( channel_url = resp . channel_url , user_id = resp . user . guest_id , duration = 600 ) # duration is in secs
chatbot . send_message ( f'i banned { resp . user . name } for 10 mins' , resp . channel_url )
elif resp . message == "*another bad word*" :
chatbot . delete_mesg ( channel_url = resp . channel_url , msg_id = resp . msg_id )
chatbot . send_message ( f"i deleted { resp . user . name } 's message" , resp . channel_url )
# or you can add a basic response hook directly like so:
chatbot . set_respond_hook ( input_ = "Hi" , response = "Hello {nickname}! sup?" , limited_to_users = None , lower_the_input = False ,
exclude_itself = True , must_be_equal = True ,
limited_to_channels = [ "my cozy chat group" ]) # you can limit by indicating chatroom's name
# you can add a welcome message for newly joined users:
chatbot . set_welcome_message ( "welcome to the my cozy chat group u/{nickname}!)" ,
limited_to_channels = [ "my cozy chat group" ])
# and a farewell message too:
chatbot . set_farewell_message ( "Too bad u/{nickname} left us :(" , limited_to_channels = [ "my cozy chat group" ])
# there are also other types of hooks like this one for invitations
@ chatbot . event . on_invitation
def on_invit ( resp ):
if resp . channel_type == CustomType . group :
invit_type = "group chat"
elif resp . channel_type == CustomType . direct :
invit_type = "DM"
print ( f"got invited to { invit_type } by { resp . data . inviter . nickname } " )
chatbot . accept_chat_invite ( resp . channel_url )
chatbot . send_message ( "Hello! I accepted your invite" , resp . channel_url )
return True
# or on ready hook
@ chatbot . event . on_ready
def report_channels ( _ ):
channels = chatbot . get_channels ()
print ( "up and running in these channels!: " )
for channel in channels :
print ( channel . name )
# reading message history from a channel
@ chatbot . event . on_ready
def report_channels ( _ ):
channels = chatbot . get_channels ()
my_channel = None
for channel in channels :
if channel . name == "My Channel" :
my_channel = channel
last_hundred_messages = chatbot . get_older_messages ( channel_url = my_channel . channel_url ,
prev_limit = 100 )
last_created_at = last_hundred_messages [ - 1 ]. created_at
while True :
messages = chatbot . get_older_messages ( channel_url = my_channel . channel_url ,
message_ts = last_created_at ,
prev_limit = 30 )
last_created_at = messages [ - 1 ]. created_at
# starting a direct chat
@ chatbot . event . on_ready
def dm_chat ( _ ):
dm_channel = chatbot . create_direct_channel ( "someuseridk" )
chatbot . send_message ( "Hey what's up?" , dm_channel . channel_url )
# starting a group chat
@ chatbot . event . on_ready
def gorup_chat ( _ ):
group_channel = chatbot . create_channel ( nicknames = [ "user1" , "user2" ], group_name = "my group" )
chatbot . send_message ( "Hey guys what's up?" , group_channel . channel_url )
chatbot . invite_user_to_channel ( group_channel . channel_url , nicknames = [ "someotheruser" ])
invite_link = chatbot . get_invite_link ( group_channel . channel_url )
chatbot . send_message ( group_channel . channel_url , f"this is our invite link: { invite_link } " )
# wanna check invitations on start?
@ chatbot . event . on_ready
def check_invites ( _ ):
invites = chatbot . get_chat_invites ()
for invite in invites :
print ( f"invited to chat by { invite . inviter } with the message { invite . last_message . message } " )
chatbot . accept_chat_invite ( invite . channel_url )
return True
# and finally, run forever...
chatbot . run_4ever ( auto_reconnect = True )
# set auto_reconnect to True so as to re-connect in case remote server shuts down the connection after some period of time