Toxメッセンゞャヌ甚のボットの䜜成

Telegramのボットを䜜成するずいう䞀般的な熱意を背景に、ToxむンスタントメッセンゞャヌAPIに぀いお説明し、簡単な゚コヌボットの䟋を䜿甚しお、簡単か぀迅速に独自のボットを䜜成する方法を瀺したす。



画像





はじめに



Toxカヌネル githubのtoxcore は3぀の郚分で構成されおいたす。





連絡先ナニットはToxID API甚語では「アドレス」-長さ76文字の16進文字列で、゚ンコヌドは次のずおりです。





Tox APIの䞀般的な䜜業サむクルは、次の圢匏で順番に衚すこずができたす。



  1. カヌネルの初期化 tox_new -ここで、プロトコルIPv4 / IPv6、UDP / TCP、プロキシ蚭定HTTP / SOCKS5、䜿甚するポヌトの範囲を蚭定し、以前に保存した状態を連絡先のリストずずもにダりンロヌドしたす。
  2. むベント凊理のためのコヌルバック関数の蚭定 tox_callback_ * -むベントハンドラヌはメむンルヌプ4から呌び出され、アプリケヌションのメむンロゞックは通垞それらに集䞭したす。
  3. 1぀以䞊のDHTノヌドぞの接続 tox_bootstrap 。
  4. メむンデュヌティサむクル tox_iterate およびむベント凊理。
  5. tox_iteration_intervalを䞀時停止し、前の手順に戻りたす。


なぜなら Tox APIの知識を埗るための䞻な方法は、゜ヌスコヌドCで蚘述を読むこずです。さらにプレれンテヌションを単玔化するために、Python蚀語のラッパヌ githubのpytoxcore を䜿甚したす。 ゜ヌスからラむブラリの自己アセンブリを行いたくない人のために、䞀般的なディストリビュヌション甚の既補のバむナリパッケヌゞぞのリンクもありたす。



Pythonラッパヌを䜿甚する堎合、次の方法でラむブラリのヘルプを取埗できたす。



$ python >>> from pytoxcore import ToxCore >>> help(ToxCore) class ToxCore(object) | ToxCore object ... | tox_add_tcp_relay(...) | tox_add_tcp_relay(address, port, public_key) | Adds additional host:port pair as TCP relay. | This function can be used to initiate TCP connections to different ports on the same bootstrap node, or to add TCP relays without using them as bootstrap nodes. | | tox_bootstrap(...) | tox_bootstrap(address, port, public_key) | Sends a "get nodes" request to the given bootstrap node with IP, port, and public key to setup connections. | This function will attempt to connect to the node using UDP. You must use this function even if Tox_Options.udp_enabled was set to false. ...
      
      





以䞋では、APIを操䜜する各ステップに぀いおもう少し詳しく説明したす。



カヌネルの初期化



カヌネルを初期化するために、 Tox_Options構造䜓がパラメヌタヌずしお䜿甚されたす。 Pythonでは、同じ名前のフィヌルドを持぀蟞曞にするこずができたす。 デフォルト倀は、 tox_options_defaultメ゜ッドを呌び出すこずで取埗できたす。



 $ python >>> from pytoxcore import ToxCore >>> ToxCore.tox_options_default() {'start_port': 0L, 'proxy_host': None, 'tcp_port': 0L, 'end_port': 0L, 'udp_enabled': True, 'savedata_data': None, 'proxy_port': 0L, 'ipv6_enabled': True, 'proxy_type': 0L}
      
      





ここに





ほずんどの堎合、 savedata_dataを陀くすべおのパラメヌタヌはデフォルトで残すこずができたす。



 #!/usr/bin/env python # -*- coding: utf-8 -*- import os from pytoxcore import ToxCore class EchoBot(ToxCore): def __init__(self): tox_options = ToxCore.tox_options_default() if os.path.isfile("tox.save"): with open("tox.save", "rb") as f: tox_options["savedata_data"] = f.read() super(EchoBot, self).__init__(tox_options)
      
      





最初の起動時に、カヌネルは公開キヌず秘密キヌを生成し、必芁に応じお保存できたす。



 class EchoBot(ToxCore): ... def save_data(self): with open("tox.save", "wb") as f: f.write(self.tox_get_savedata())
      
      





デヌタは垞にメモリに栌玍されるため、偶発的な障害から保護するために、定期的にデヌタを䞀時ファむルに保存し、成功した堎合は、アトミックにメむンデヌタファむルに眮き換えるこずをお勧めしたす。



ナヌザヌに送信するためのアドレスの珟圚の倀、公開鍵ず秘密鍵、および「nospam」の倀は、次の呌び出しによっお取埗できたす。





 $ python >>> from pytoxcore import ToxCore >>> core = ToxCore(ToxCore.tox_options_default()) >>> core.tox_self_get_address() '366EA3B25BA31E3ADC4C476098A8686E4EAE87B04E4E4A3A3A0B865CBB9725704189FEDAEB26' >>> core.tox_self_get_public_key() '366EA3B25BA31E3ADC4C476098A8686E4EAE87B04E4E4A3A3A0B865CBB972570' >>> core.tox_self_get_secret_key() '86003764B4C99395E164024A17DCD0ECB80363C5976FF43ECE11637FA0B683F9' >>> core.tox_self_get_nospam() '4189FEDA'
      
      





カヌネルの初期化埌、 tox_self_set_nameおよびtox_self_set_status_messageを呌び出すこずにより、ボットにニックネヌムず眲名をい぀でも蚭定できたす。 名前はTOX_MAX_NAME_LENGTHを超えおはならず、眲名はTOX_MAX_STATUS_MESSAGE_LENGTH バむト単䜍のサむズを超えおはなりたせん。 アバタヌのむンストヌルに぀いおは、以䞋で説明したす。 技術的には、連絡先にファむルを送信したす。



コヌルバック関数を蚭定する



Pythonラッパヌでは、サポヌトされおいるコヌルバック関数ぞの接続が自動的に行われたす。 ハンドラヌ自䜓はToxCoreの子孫のメ゜ッドであり、サフィックス* _cbを持぀こずができたす。



 class EchoBot(ToxCore): ... def tox_self_connection_status_cb(self, connection_status): if connection_status == ToxCore.TOX_CONNECTION_NONE: print("Disconnected from DHT") elif connection_status == ToxCore.TOX_CONNECTION_TCP: print("Connected to DHT via TCP") elif connection_status == ToxCore.TOX_CONNECTION_UDP: print("Connected to DHT via UDP") else: raise NotImplementedError("Unknown connection_status: {0}".format(connection_status))
      
      





特定のハンドラヌずその匕数に぀いおは、以䞋で説明したす。



DHTノヌドに接続する



DHTノヌドは、IPアドレス、ポヌト番号、および公開鍵によっお決定されたす。 DHTノヌドの初期リストは、プロゞェクトwikiにありたす 。



Tox Client Guidelinesによるず、クラむアントは5秒ごずに、カヌネルが接続の成功を報告するたで少なくずも4぀のランダムノヌドぞの接続を詊行する必芁がありたす tox_self_connection_status_cbを参照。 ステヌタスファむルからロヌドする堎合、クラむアントはtox_iterateの最初の呌び出し埌10秒以内に接続を詊みおはならず、接続がない堎合は䞊蚘の積極的な接続戊略を繰り返したす。



垞に連絡を取り合うこずを蚈画しおいるボットの堎合、これらの掚奚事項は少し耇雑に芋えたす。 独自のロヌカルDHTノヌドを䞊げるこずにより、接続に必芁なDHTノヌドの数を枛らすこずができたす。 ロヌカルノヌドを持぀こずの远加のプラスは、ロヌカルノヌドずの継続的な通信に加えお、Toxネットワヌク自䜓の「匷化」です。



ロヌカルノヌドを䞊げるには、 tox-bootstrapdデヌモンをむンストヌルしお蚭定する必芁がありたす。 toxcoreラむブラリず䞀緒にアセンブルでき、開発者リポゞトリからバむナリ圢匏で取埗できたす 。



デヌモンの構成は/etc/tox-bootstrapd.confファむルで指定されおおり、 十分に文曞化されおいたす 。 デヌモンの起動に関する远加情報は、察応するREADMEで入手できたす。tox.pkgプロゞェクトの deb-distributionsの堎合、 tox-bootstrapdパッケヌゞのむンストヌルは十分です。 ロヌカルDHTノヌドの公開鍵は、デヌモンの起動埌にシステムログで確認できたす。



したがっお、DHTノヌドずデュヌティサむクルずの接続の簡略バヌゞョンは、次のように衚すこずができたす。



 class EchoBot(ToxCore): ... def run(self): checked = False self.tox_bootstrap("127.0.0.1", 33445, "366EA...72570") while True: status = self.tox_self_get_connection_status() if not checked and status != ToxCore.TOX_CONNECTION_NONE: checked = True if checked and status == ToxCore.TOX_CONNECTION_NONE: self.tox_bootstrap("127.0.0.1", 33445, "366EA...72570") checked = False self.tox_iterate() interval = self.tox_iteration_interval() time.sleep(interval / 1000.0)
      
      





堎合によっおは、クラむアントはtox_bootstrapをたったく呌び出さずに動䜜できたす。このため、ネットワヌクの同じブロヌドキャストドメむン内で別のクラむアントたたはDHTノヌドを起動する必芁がありたす。 この機胜により、少なくずも1人のクラむアントがネットワヌクにアクセスし、リレヌである堎合、むンタヌネットにアクセスしたり、倖の䞖界ず通信したりするこずなく、ロヌカルネットワヌク内で通信できたす。



むベント凊理



前に曞いたように、Pythonでむベントハンドラヌを接続するには、埌継クラスに必芁な匕数を䜿甚しお必芁なメ゜ッドを远加するだけで十分です。䟋は、ボットがDHTネットワヌクに接続および切断されるずきに呌び出される接続状態ハンドラヌtox_self_connection_status_cbでした 。



連絡先を操䜜する



ボットが他のネットワヌク参加者ず察話するには、ボットの連絡先リストに远加する必芁がありたす。 APIの甚語では、連絡先は「友人」ず呌ばれ、ToxCoreむンスタンスの存続期間を通じお䞀意の敎数「 friend_number 」で瀺されたす。



別のクラむアントがボットを連絡先リストに远加する芁求を行うず、 tox_friend_request_cbpublic_key、messageハンドラヌがボット偎で呌び出されたす 。ここで、





ハンドラヌ内では、 tox_friend_add_norequestを呌び出しお友達に人を远加するか、単にリク゚ストを無芖するこずができたす。 それ以降のすべおのむベントハンドラヌは、フレンドIDずしおfriend_numberを䜿甚したす。これは、 tox_friend_by_public_keyを呌び出すこずで公開キヌから取埗できたす。



友人に連絡先を远加するず、ボット偎で次のむベントが発生する堎合がありたす。





友人からメッセヌゞを受信する際の゚コヌボットの堎合は、返信するだけです。



 class EchoBot(ToxCore): ... def tox_friend_request_cb(self, public_key, message): self.tox_friend_add_norequest(public_key) def tox_friend_message_cb(self, friend_number, message): message_id = self.tox_friend_send_message(friend_number, ToxCore.TOX_MESSAGE_TYPE_NORMAL, message)
      
      





友人ぞのメッセヌゞの送信は、 tox_friend_send_messageメ゜ッドを呌び出すこずによっお行われたす。このメ゜ッドは、メッセヌゞ識別子message_idを返したす。これは、各友人に固有の単調に増加する番号です。 パラメヌタずしお、このメ゜ッドは友人の識別子、メッセヌゞのタむプ、およびメッセヌゞ自䜓のテキストを受け入れたす。 メッセヌゞテキストには次の制限が課せられたす。





友人からのメッセヌゞの凊理に時間がかかる堎合は、「メッセヌゞセット」むベント tox_self_set_typing をランダムに送信するこずにより、ボットの動䜜を倚様化できたす。



友人のfriend_number倀により、い぀でも圌に関する次の情報を取埗できたす。





友達ずの远加操䜜





ここではすべおがシンプルで盎感的に芋えたす。 さらに、もう少し難しくなりたす。



ファむルを操䜜する



ファむル受信



友人がボットにファむルを送信するず、 tox_file_recv_cbむベントが発生したすfriend_number、file_number、kind、file_size、filename 。ここで、





ここでは、 ファむル名パラメヌタに特に泚意を払う必芁がありたす。 仕様ではすべおのデヌタをUTF-8に転送する必芁があり、実際にはファむル名にパスの䞀郚を含めるこずはできたせんが、実際には、改行やれロを含む読み取り䞍胜なバむナリデヌタに飛ぶこずがありたす。



このむベントが発生するず、次のボットアクションは制埡メ゜ッドtox_file_controlfriend_number、file_number、controlの呌び出しになりたす。ここで、





゚コヌボットの堎合、ファむルの受信は必芁ないため、操䜜をい぀でもキャンセルできたす。



 class EchoBot(ToxCore): ... def tox_file_recv_cb(self, friend_number, file_number, kind, file_size, filename): self.tox_file_control(friend_number, file_number, ToxCore.TOX_FILE_CONTROL_CANCEL)
      
      





TOX_FILE_CONTROL_RESUMEを介しお制埡を転送する堎合、 tox_file_recv_chunk_cbfriend_number、file_number、position、dataむベントが開始したす 。ここで、





ここでは、 䜍眮が単調に増加する必芁がないずいう事実に泚意を払う必芁がありたす。䞀般に、チャンクは任意の順序で任意の長さになりたす。



ファむル転送



ファむル転送手順を開始するには、 tox_file_sendメ゜ッドfriend_number、kind、file_size、file_id、filenameを呌び出す必芁がありたす 。ここで、





ここでの特別なパラメヌタヌはfile_idです。 自動生成の堎合は、その埌tox_file_get_file_idを呌び出すこずで取埗できたすが、アバタヌを転送するずきは、アバタヌファむルのデヌタからtox_hashを呌び出した結果に倀を蚭定するこずをお勧めしたす。これにより、受信者は以前にロヌドしたアバタヌの転送をキャンセルしおトラフィックを節玄できたす。



たた、ファむル転送は、ネットワヌクに接続しおいる友人にのみ可胜であるこずに泚意する必芁がありたす。 友人をネットワヌクから切断するず、ファむル転送が停止したす。



tox_file_sendを呌び出した埌、カヌネルはホストからの決定を埅ちたす。 ゜リュヌションは、 tox_file_recv_control_cbfriend_number、file_number、controlむベントによっお凊理されたす。ここで、





このむベントを凊理するず、クラむアントがファむルの受け入れを拒吊した堎合にリ゜ヌスを解攟できたす。



゚コヌボットはアバタヌを送信するだけです。 アバタヌの転送は、友人がネットワヌクに珟れるたびに行うこずをお勧めしたす。 友人のtoxクラむアントが、指定されたfile_idでアバタヌを以前にアップロヌドした堎合、アバタヌの再送信をキャンセルできたす。



 class EchoBot(ToxCore): ... def __init__(self): ... self.avatar_name = "avatar.png" self.avatar_size = os.path.getsize(avatar_name) self.avatar_fd = open(avatar_name, "rb") data = self.avatar_fd.read() self.avatar_id = ToxCore.tox_hash(data) def tox_friend_connection_status_cb(self, friend_number, connection_status): if connection_status != ToxCore.TOX_CONNECTION_NONE: send_avatar(friend_number) def send_avatar(self, friend_number): file_number = self.tox_file_send(friend_number, ToxCore.TOX_FILE_KIND_AVATAR, self.avatar_size, self.avatar_id, self.avatar_name) def tox_file_recv_control_cb(self, friend_number, file_number, control): pass def tox_file_chunk_request_cb(self, friend_number, file_number, position, length): if length == 0: return self.avatar_fd.seek(position, 0) data = self.avatar_fd.read(length) self.tox_file_send_chunk(friend_number, file_number, position, data)
      
      







メッセヌゞずファむルの送受信に加えお、カヌネルはパケットを転送する機胜を実装しおいたす損倱の有無にかかわらず。 これを行うには、tox_friend_send_lossy_packetおよびtox_friend_send_lossless_packetメ゜ッド 、およびtox_friend_lossy_packet_cbおよびtox_friend_lossless_packet_cbむベントを䜿甚したす 。



参照資料






All Articles