diff --git a/docs/doctrees/creatingacommand.doctree b/docs/doctrees/creatingacommand.doctree
index bdc5f93c..0898c66f 100644
Binary files a/docs/doctrees/creatingacommand.doctree and b/docs/doctrees/creatingacommand.doctree differ
diff --git a/docs/doctrees/environment.pickle b/docs/doctrees/environment.pickle
index f695f38c..4e9f7c4f 100644
Binary files a/docs/doctrees/environment.pickle and b/docs/doctrees/environment.pickle differ
diff --git a/docs/html/_sources/creatingacommand.rst.txt b/docs/html/_sources/creatingacommand.rst.txt
index 341e2437..e617e69f 100644
--- a/docs/html/_sources/creatingacommand.rst.txt
+++ b/docs/html/_sources/creatingacommand.rst.txt
@@ -22,7 +22,6 @@ A Command code looks like this: ::
# This code is run every time the command is called
await data.reply("Pong!")
-
Creating a new Command
------------------------------------
@@ -33,7 +32,7 @@ Try to keep the name as short as possible, while staying specific enough so no o
Next, create a new Python file with the ``name`` you have thought of.
The previously mentioned "spaghetti" command should have a file called ``spaghetti.py``.
-Then, in the first row of the file, import the :py:class:`Command` class from :py:mod:`royalnet`, and create a new class inheriting from it: ::
+Then, in the first row of the file, import the :py:class:`Command` class from royalnet, and create a new class inheriting from it: ::
from royalnet.commands import Command
@@ -61,6 +60,36 @@ To send a message in the chat the command was called in, you can use the :py:met
description = "Send a spaghetti emoji in the chat."
async def run(self, args, data):
- data.reply("๐")
+ await data.reply("๐")
-And it's done! The command is now ready to be used in a bot!
+And... it's done! The command is ready to be added to a bot!
+
+Coroutines and slow operations
+------------------------------------
+
+You may have noticed that in the previous example I wrote ``await data.reply("๐")`` instead of just ``data.reply("๐")``.
+
+This is because :py:meth:`CommandData.reply` isn't a simple method: it is a coroutine, a special kind of function that
+ can be executed separately from the rest of the code, allowing the bot to do other things in the meantime.
+
+By adding the ``await`` keyword before the ``data.reply("๐")``, we tell the bot that it can do other things, like
+ receiving new messages, while the message is being sent.
+
+You should avoid running slow normal functions inside bot commands, as they will stop the bot from working until they
+ are finished and may cause bugs in other parts of the code! ::
+
+ async def run(self, args, data):
+ # Don't do this!
+ image = download_1_terabyte_of_spaghetti("right_now", from="italy")
+ ...
+
+If the slow function you want does not cause any side effect, you can wrap it with the :ref:`royalnet.utils.asyncify`
+ function: ::
+
+ async def run(self, args, data):
+ # If the called function has no side effect, you can do this!
+ image = await asyncify(download_1_terabyte_of_spaghetti, "right_now", from="italy")
+ ...
+
+Avoid using :py:func:`time.sleep` function, as it is considered a slow operation: use instead :py:func:`asyncio.sleep`,
+ a coroutine that does the same exact thing.
diff --git a/docs/html/creatingacommand.html b/docs/html/creatingacommand.html
index e8fbdd6c..d2dc83fb 100644
--- a/docs/html/creatingacommand.html
+++ b/docs/html/creatingacommand.html
@@ -84,6 +84,7 @@
- Royalnet Commands
- API Reference
@@ -178,7 +179,7 @@ Itโs the name your command will be called with: for example, the โspaghetti
Try to keep the name as short as possible, while staying specific enough so no other command will have the same name.
Next, create a new Python file with the name
you have thought of.
The previously mentioned โspaghettiโ command should have a file called spaghetti.py
.
-Then, in the first row of the file, import the Command
class from royalnet
, and create a new class inheriting from it:
+Then, in the first row of the file, import the Command
class from royalnet, and create a new class inheriting from it:
from royalnet.commands import Command
class SpaghettiCommand(Command):
@@ -204,10 +205,38 @@ The previously mentioned โspaghettiโ command should have a file called description = "Send a spaghetti emoji in the chat."
async def run(self, args, data):
- data.reply("๐")
+ await data.reply("๐")
-And itโs done! The command is now ready to be used in a bot!
+Andโฆ itโs done! The command is ready to be added to a bot!
+
+
+
Coroutines and slow operations
+
You may have noticed that in the previous example I wrote await data.reply("๐")
instead of just data.reply("๐")
.
+
+- This is because
CommandData.reply()
isnโt a simple method: it is a coroutine, a special kind of function that can be executed separately from the rest of the code, allowing the bot to do other things in the meantime.
+
+- By adding the
await
keyword before the data.reply("๐")
, we tell the bot that it can do other things, like receiving new messages, while the message is being sent.
+
+- You should avoid running slow normal functions inside bot commands, as they will stop the bot from working until they
are finished and may cause bugs in other parts of the code!
+async def run(self, args, data):
+ # Don't do this!
+ image = download_1_terabyte_of_spaghetti("right_now", from="italy")
+ ...
+
+
+
+- If the slow function you want does not cause any side effect, you can wrap it with the royalnet.utils.asyncify
function:
+async def run(self, args, data):
+ # If the called function has no side effect, you can do this!
+ image = await asyncify(download_1_terabyte_of_spaghetti, "right_now", from="italy")
+ ...
+
+
+
+- Avoid using
time.sleep()
function, as it is considered a slow operation: use instead asyncio.sleep()
, a coroutine that does the same exact thing.
+
+
diff --git a/docs/html/index.html b/docs/html/index.html
index d829177a..3165ca2c 100644
--- a/docs/html/index.html
+++ b/docs/html/index.html
@@ -154,6 +154,7 @@
- Royalnet Commands
- API Reference
diff --git a/docs/html/searchindex.js b/docs/html/searchindex.js
index 1c10fd38..efd4c5da 100644
--- a/docs/html/searchindex.js
+++ b/docs/html/searchindex.js
@@ -1 +1 @@
-Search.setIndex({docnames:["apireference","creatingacommand","index"],envversion:{"sphinx.domains.c":1,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":1,"sphinx.domains.javascript":1,"sphinx.domains.math":2,"sphinx.domains.python":1,"sphinx.domains.rst":1,"sphinx.domains.std":1,"sphinx.ext.intersphinx":1,sphinx:56},filenames:["apireference.rst","creatingacommand.rst","index.rst"],objects:{"royalnet.audio":{FileAudioSource:[0,1,1,""],YtdlDiscord:[0,1,1,""],YtdlFile:[0,1,1,""],YtdlInfo:[0,1,1,""],YtdlMp3:[0,1,1,""]},"royalnet.audio.FileAudioSource":{is_opus:[0,2,1,""],read:[0,2,1,""]},"royalnet.audio.YtdlDiscord":{"delete":[0,2,1,""],convert_to_pcm:[0,2,1,""],create_and_ready_from_url:[0,2,1,""],create_from_url:[0,2,1,""],info:[0,2,1,""],pcm_available:[0,2,1,""],ready_up:[0,2,1,""],spawn_audiosource:[0,2,1,""]},"royalnet.audio.YtdlFile":{"delete":[0,2,1,""],_default_ytdl_args:[0,3,1,""],download_file:[0,2,1,""],download_from_url:[0,2,1,""],has_info:[0,2,1,""],is_downloaded:[0,2,1,""],open:[0,2,1,""],update_info:[0,2,1,""]},"royalnet.audio.YtdlInfo":{__init__:[0,2,1,""],_default_ytdl_args:[0,3,1,""],retrieve_for_url:[0,2,1,""],to_discord_embed:[0,2,1,""]},"royalnet.audio.YtdlMp3":{"delete":[0,2,1,""],convert_to_mp3:[0,2,1,""],create_and_ready_from_url:[0,2,1,""],create_from_url:[0,2,1,""],info:[0,2,1,""],pcm_available:[0,2,1,""],ready_up:[0,2,1,""]},"royalnet.bots":{DiscordBot:[0,1,1,""],DiscordConfig:[0,1,1,""],GenericBot:[0,1,1,""],TelegramBot:[0,1,1,""],TelegramConfig:[0,1,1,""]},"royalnet.bots.DiscordBot":{_bot_factory:[0,2,1,""],_data_factory:[0,2,1,""],_init_client:[0,2,1,""],_init_voice:[0,2,1,""],_interface_factory:[0,2,1,""],add_to_music_data:[0,2,1,""],advance_music_data:[0,2,1,""],interface_name:[0,3,1,""],run:[0,2,1,""],update_activity_with_source_title:[0,2,1,""]},"royalnet.bots.GenericBot":{_data_factory:[0,2,1,""],_init_commands:[0,2,1,""],_init_database:[0,2,1,""],_init_royalnet:[0,2,1,""],_interface_factory:[0,2,1,""],_network_handler:[0,2,1,""],interface_name:[0,3,1,""],run:[0,2,1,""]},"royalnet.bots.TelegramBot":{_data_factory:[0,2,1,""],_handle_update:[0,2,1,""],_init_client:[0,2,1,""],_interface_factory:[0,2,1,""],interface_name:[0,3,1,""],run:[0,2,1,""]},"royalnet.commands":{Command:[0,1,1,""],CommandArgs:[0,1,1,""],CommandData:[0,1,1,""],CommandInterface:[0,1,1,""]},"royalnet.commands.Command":{description:[0,3,1,""],name:[0,3,1,""],require_alchemy_tables:[0,3,1,""],run:[0,2,1,""],syntax:[0,3,1,""]},"royalnet.commands.CommandArgs":{__getitem__:[0,2,1,""],joined:[0,2,1,""],match:[0,2,1,""],optional:[0,2,1,""]},"royalnet.commands.CommandData":{get_author:[0,2,1,""],reply:[0,2,1,""]},"royalnet.commands.CommandInterface":{alchemy:[0,3,1,""],bot:[0,3,1,""],loop:[0,3,1,""],name:[0,3,1,""],net_request:[0,2,1,""],prefix:[0,3,1,""],register_net_handler:[0,2,1,""],unregister_net_handler:[0,2,1,""]},"royalnet.database":{Alchemy:[0,1,1,""],DatabaseConfig:[0,1,1,""],relationshiplinkchain:[0,4,1,""]},"royalnet.database.Alchemy":{__init__:[0,2,1,""],_create_tables:[0,2,1,""],session_acm:[0,2,1,""],session_cm:[0,2,1,""]},"royalnet.error":{CurrentlyDisabledError:[0,5,1,""],ExternalError:[0,5,1,""],FileTooBigError:[0,5,1,""],InvalidConfigError:[0,5,1,""],InvalidInputError:[0,5,1,""],NoneFoundError:[0,5,1,""],RoyalnetRequestError:[0,5,1,""],RoyalnetResponseError:[0,5,1,""],TooManyFoundError:[0,5,1,""],UnregisteredError:[0,5,1,""],UnsupportedError:[0,5,1,""]},"royalnet.network":{ConnectionClosedError:[0,5,1,""],NetworkError:[0,5,1,""],NotConnectedError:[0,5,1,""],NotIdentifiedError:[0,5,1,""],Package:[0,1,1,""],Request:[0,1,1,""],Response:[0,1,1,""],ResponseError:[0,1,1,""],ResponseSuccess:[0,1,1,""],RoyalnetConfig:[0,1,1,""],RoyalnetLink:[0,1,1,""],RoyalnetServer:[0,1,1,""]},"royalnet.network.Package":{__init__:[0,2,1,""],from_dict:[0,2,1,""],from_json_bytes:[0,2,1,""],from_json_string:[0,2,1,""],reply:[0,2,1,""],to_dict:[0,2,1,""],to_json_bytes:[0,2,1,""],to_json_string:[0,2,1,""]},"royalnet.network.Request":{from_dict:[0,2,1,""],to_dict:[0,2,1,""]},"royalnet.network.Response":{from_dict:[0,2,1,""],raise_on_error:[0,2,1,""],to_dict:[0,2,1,""]},"royalnet.network.ResponseError":{raise_on_error:[0,2,1,""]},"royalnet.network.ResponseSuccess":{raise_on_error:[0,2,1,""]},"royalnet.network.RoyalnetLink":{connect:[0,2,1,""],identify:[0,2,1,""],receive:[0,2,1,""],request:[0,2,1,""],run:[0,2,1,""],send:[0,2,1,""]},"royalnet.network.RoyalnetServer":{find_client:[0,2,1,""],find_destination:[0,2,1,""],listener:[0,2,1,""],route_package:[0,2,1,""],serve:[0,2,1,""],start:[0,2,1,""]},"royalnet.utils":{NetworkHandler:[0,1,1,""],andformat:[0,4,1,""],asyncify:[0,4,1,""],cdj:[0,4,1,""],discord_escape:[0,4,1,""],fileformat:[0,4,1,""],numberemojiformat:[0,4,1,""],ordinalformat:[0,4,1,""],parse_5etools_entry:[0,4,1,""],plusformat:[0,4,1,""],safeformat:[0,4,1,""],sleep_until:[0,4,1,""],splitstring:[0,4,1,""],telegram_escape:[0,4,1,""],ytdldateformat:[0,4,1,""]},"royalnet.utils.NetworkHandler":{message_type:[0,3,1,""]},"royalnet.web":{Royalprint:[0,1,1,""],create_app:[0,4,1,""]},royalnet:{audio:[0,0,0,"-"],bots:[0,0,0,"-"],commands:[0,0,0,"-"],database:[0,0,0,"-"],error:[0,0,0,"-"],network:[0,0,0,"-"],utils:[0,0,0,"-"],web:[0,0,0,"-"]}},objnames:{"0":["py","module","Python module"],"1":["py","class","Python class"],"2":["py","method","Python method"],"3":["py","attribute","Python attribute"],"4":["py","function","Python function"],"5":["py","exception","Python exception"]},objtypes:{"0":"py:module","1":"py:class","2":"py:method","3":"py:attribute","4":"py:function","5":"py:exception"},terms:{"20m":0,"byte":0,"class":[0,1],"default":0,"final":0,"function":0,"import":1,"int":0,"new":[0,2],"null":0,"return":0,"short":1,"static":0,"super":1,"true":0,"try":[0,1],"while":[0,1],And:1,That:0,The:[0,1],Then:[0,1],These:0,Use:0,__dict__:0,__doc__:0,__getitem__:0,__init__:[0,1],__module__:0,__slots__:0,__weakref__:0,_bot_factori:0,_create_t:0,_data_factori:0,_default_ytdl_arg:0,_handle_upd:0,_init_cli:0,_init_command:0,_init_databas:0,_init_royalnet:0,_init_voic:0,_interface_factori:0,_network_handl:0,abl:0,about:0,abstracteventloop:0,access:0,accur:0,add:0,add_to_music_data:0,added:0,adding:[0,1],addit:0,address:0,advance_music_data:0,akin:0,alchemi:0,all:0,allow:0,also:0,altern:0,alwai:0,amount:0,andformat:0,ani:0,anoth:0,anymor:0,anystr:0,api:2,app:0,applic:0,arg:[0,1],argument:0,around:0,arrai:0,async:[0,1],asyncifi:0,asyncio:0,asyncron:0,attempt:0,attribut:[0,1],audio:2,audiosourc:0,author:0,autocomplet:0,automat:0,avail:0,await:1,base:0,been:0,being:0,between:0,big:0,block:0,blockingli:0,blueprint:0,bool:0,bot:[1,2],both:0,bufferediobas:0,call:[0,1],callabl:0,can:[0,1],cancel:0,cannot:0,caution:0,cdj:0,chain:0,chang:0,change_pres:0,channel:0,charact:0,chat:[0,1],check:0,class_:0,classmethod:0,client:0,close:0,clue:0,code:[0,1],command:2,commandarg:0,commanddata:[0,1],commandinterfac:0,commun:0,complet:0,compon:0,config:0,config_obj:0,configur:0,connect:0,connectedcli:0,connectionclosederror:0,consum:0,contain:0,context:0,convers:0,convert:0,convert_to_mp3:0,convert_to_pcm:0,core:0,coroutin:0,correctli:0,correspond:0,creat:[0,2],create_and_ready_from_url:0,create_app:0,create_from_url:0,current:0,currentlydisablederror:0,custom:0,dai:0,data:[0,1],databas:2,database_config:0,database_uri:0,databaseconfig:0,date:0,datetim:0,db_path:0,declar:0,def:1,delet:0,describ:0,descript:[0,1],destin:0,destination_conv_id:0,detail:0,dfile:0,dict:0,dictionari:0,disabl:0,discord:0,discord_config:0,discord_escap:0,discordbot:0,discordcli:0,discordconfig:0,displai:0,doc:0,docstr:0,document:2,doe:0,doesn:0,don:0,done:1,download:0,download_fil:0,download_from_url:0,dynam:0,eas:0,edit:0,either:0,element:0,emb:0,emoji:1,empti:0,encod:0,end:0,ending_class:0,engin:0,enough:1,ensur:0,entri:0,envvar:0,epoch:0,error:2,error_data:0,error_if_non:0,escap:0,even:0,event:0,everi:[0,1],everyth:0,exampl:[0,1],except:0,execut:0,exist:0,expect:0,ext:0,externalerror:0,extra_info:0,extract:0,extract_info:0,fals:0,featur:0,fetch:0,file:[0,1],fileaudiosourc:0,fileformat:0,filenam:0,filetoobigerror:0,find:0,find_client:0,find_destin:0,first:1,flask:0,follow:0,format:0,found:0,from:[0,1],from_dict:0,from_json_byt:0,from_json_str:0,from_object:0,fullfil:0,gener:0,genericbot:0,get:0,get_author:0,github:2,greater:0,group:0,guild:0,handl:0,handler:0,has:0,has_info:0,have:[0,1],how:0,html:0,http:0,identifi:0,identity_column_nam:0,identity_t:0,ifi:0,ignor:0,ignoreerror:0,import_nam:0,incom:0,incomplet:0,index:[0,2],inf:0,info:0,inform:0,inherit:[0,1],initi:0,input:0,insid:1,instanc:0,instead:0,interfac:[0,1],interface_nam:0,invalid:0,invalidconfigerror:0,invalidinputerror:0,is_download:0,is_opu:0,isn:0,item:0,join:0,json:0,jsonabl:0,just:[0,1],keep:1,kei:0,kwarg:0,last:0,less:0,like:[0,1],link:0,link_typ:0,list:0,listen:0,login:0,look:[0,1],loop:0,made:0,main:0,mainli:0,maintain:0,make:0,manag:0,markup:0,master_secret:0,master_t:0,master_uri:0,match:0,max:0,mean:0,memori:0,mention:1,messag:[0,1],message_typ:0,method:[0,1],middl:0,might:0,minimum:0,miscellan:0,miss:0,month:0,more:0,multipl:0,music_data:0,must:0,name:[0,1],need:0,net_request:0,network:2,network_handl:0,networkerror:0,networkhandl:0,next:[0,1],nid:0,no_warn:0,nobodi:0,node:0,non:0,none:0,nonefounderror:0,noplaylist:0,notat:0,notconnectederror:0,noth:0,notidentifiederror:0,notimpl:0,now:[0,1],number:0,numberemojiformat:0,object:0,offset:0,onc:[0,1],one:0,ones:0,onli:0,open:0,option:0,optional_arg:0,opu:0,ordinalformat:0,org:0,other:[0,1],otherwis:0,outdat:0,output:0,outtmpl:0,overrid:1,packag:0,packet:0,page:0,paramet:0,parse_5etools_entri:0,pass:0,path:0,pattern:0,pcm:0,pcm_avail:0,pickl:0,ping:1,pingcommand:1,plai:[0,1],plusformat:0,pong:1,port:0,possibl:[0,1],prefix:0,prepar:0,prepend:0,presenc:0,previous:1,probabl:0,properti:0,python:1,quiet:0,rais:0,raise_on_error:0,read:0,readi:1,ready_up:0,real:0,realli:0,receiv:0,reciev:0,recreat:0,refer:2,regex:0,regist:0,register_net_handl:0,relat:0,relationshiplinkchain:0,remov:0,replac:0,repli:[0,1],request:0,request_dict:0,request_handl:0,requir:0,require_alchemy_t:0,require_at_least:0,required_arg:0,required_secret:0,required_t:0,respect:1,respons:0,responseerror:0,responsesuccess:0,result:0,retriev:0,retrieve_for_url:0,right:0,root_path:0,rout:0,route_packag:0,row:[0,1],royalcod:0,royalnet:0,royalnet_config:0,royalnetconfig:0,royalnetlink:0,royalnetrequesterror:0,royalnetresponseerror:0,royalnetserv:0,royalprint:0,run:[0,1],safeformat:0,same:1,script:1,second:0,secret:0,secret_kei:0,select:0,self:[0,1],send:[0,1],sent:[0,1],sentry_dsn:0,separ:0,sequenc:0,serv:0,server:0,session_acm:0,session_cm:0,set:0,should:[0,1],signal:0,singl:0,skip:0,sleep_until:0,small:[0,1],someth:0,somewher:0,song:0,sourc:0,source_conv_id:0,space:0,spaghetti:1,spaghetticommand:1,spawn_audiosourc:0,specif:[0,1],specifi:0,splitstr:0,sqlalchemi:0,stai:1,start:[0,1],starting_class:0,statement:0,static_fold:0,static_url_path:0,statu:0,store:0,str:0,stream:0,string:0,subdomain:0,submodul:0,success:0,support:0,syntax:0,tabl:0,task:0,telegram:0,telegram_config:0,telegram_escap:0,telegrambot:0,telegramconfig:0,template_fold:0,temporar:0,text:0,than:0,thei:0,them:0,therefor:0,thi:[0,1],think:1,thought:1,through:0,time:[0,1],titl:0,to_dict:0,to_discord_emb:0,to_json_byt:0,to_json_str:0,token:0,too:0,toomanyfounderror:0,tupl:0,two:0,type:[0,1],underscor:0,undescrib:0,unexpect:0,unexpectedli:0,union:0,unregister_net_handl:0,unregisterederror:0,unsupportederror:0,until:0,updat:0,update_activity_with_source_titl:0,update_info:0,uri:0,url:0,url_default:0,url_prefix:0,use:[0,1],used:[0,1],useful:0,user:0,uses:0,using:0,usual:0,utf8:0,util:2,uuid:0,valid:0,valu:0,variabl:0,variou:0,video:0,voic:0,wai:0,wait:0,want:[0,1],web:2,websocket:0,websocketserverprotocol:0,weird:0,welcom:2,went:0,were:0,what:1,when:[0,1],whenev:1,where:0,which:0,why:0,without:0,word:0,work:0,worth:0,would:0,wrapper:0,written:0,wrong:0,year:0,yet:0,you:[0,1],your:1,youtub:0,youtube_dl:0,youtubedl:0,ytdl_arg:0,ytdl_file:0,ytdldateformat:0,ytdldiscord:0,ytdlfile:0,ytdlinfo:0,ytdlmp3:0,yyyi:0,yyyymmdd:0},titles:["API Reference","Royalnet Commands","royalnet"],titleterms:{"new":1,api:0,audio:0,bot:0,command:[0,1],creat:1,databas:0,error:0,link:2,network:0,refer:0,royalnet:[1,2],some:2,useful:2,util:0,web:0}})
\ No newline at end of file
+Search.setIndex({docnames:["apireference","creatingacommand","index"],envversion:{"sphinx.domains.c":1,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":1,"sphinx.domains.javascript":1,"sphinx.domains.math":2,"sphinx.domains.python":1,"sphinx.domains.rst":1,"sphinx.domains.std":1,"sphinx.ext.intersphinx":1,sphinx:56},filenames:["apireference.rst","creatingacommand.rst","index.rst"],objects:{"royalnet.audio":{FileAudioSource:[0,1,1,""],YtdlDiscord:[0,1,1,""],YtdlFile:[0,1,1,""],YtdlInfo:[0,1,1,""],YtdlMp3:[0,1,1,""]},"royalnet.audio.FileAudioSource":{is_opus:[0,2,1,""],read:[0,2,1,""]},"royalnet.audio.YtdlDiscord":{"delete":[0,2,1,""],convert_to_pcm:[0,2,1,""],create_and_ready_from_url:[0,2,1,""],create_from_url:[0,2,1,""],info:[0,2,1,""],pcm_available:[0,2,1,""],ready_up:[0,2,1,""],spawn_audiosource:[0,2,1,""]},"royalnet.audio.YtdlFile":{"delete":[0,2,1,""],_default_ytdl_args:[0,3,1,""],download_file:[0,2,1,""],download_from_url:[0,2,1,""],has_info:[0,2,1,""],is_downloaded:[0,2,1,""],open:[0,2,1,""],update_info:[0,2,1,""]},"royalnet.audio.YtdlInfo":{__init__:[0,2,1,""],_default_ytdl_args:[0,3,1,""],retrieve_for_url:[0,2,1,""],to_discord_embed:[0,2,1,""]},"royalnet.audio.YtdlMp3":{"delete":[0,2,1,""],convert_to_mp3:[0,2,1,""],create_and_ready_from_url:[0,2,1,""],create_from_url:[0,2,1,""],info:[0,2,1,""],pcm_available:[0,2,1,""],ready_up:[0,2,1,""]},"royalnet.bots":{DiscordBot:[0,1,1,""],DiscordConfig:[0,1,1,""],GenericBot:[0,1,1,""],TelegramBot:[0,1,1,""],TelegramConfig:[0,1,1,""]},"royalnet.bots.DiscordBot":{_bot_factory:[0,2,1,""],_data_factory:[0,2,1,""],_init_client:[0,2,1,""],_init_voice:[0,2,1,""],_interface_factory:[0,2,1,""],add_to_music_data:[0,2,1,""],advance_music_data:[0,2,1,""],interface_name:[0,3,1,""],run:[0,2,1,""],update_activity_with_source_title:[0,2,1,""]},"royalnet.bots.GenericBot":{_data_factory:[0,2,1,""],_init_commands:[0,2,1,""],_init_database:[0,2,1,""],_init_royalnet:[0,2,1,""],_interface_factory:[0,2,1,""],_network_handler:[0,2,1,""],interface_name:[0,3,1,""],run:[0,2,1,""]},"royalnet.bots.TelegramBot":{_data_factory:[0,2,1,""],_handle_update:[0,2,1,""],_init_client:[0,2,1,""],_interface_factory:[0,2,1,""],interface_name:[0,3,1,""],run:[0,2,1,""]},"royalnet.commands":{Command:[0,1,1,""],CommandArgs:[0,1,1,""],CommandData:[0,1,1,""],CommandInterface:[0,1,1,""]},"royalnet.commands.Command":{description:[0,3,1,""],name:[0,3,1,""],require_alchemy_tables:[0,3,1,""],run:[0,2,1,""],syntax:[0,3,1,""]},"royalnet.commands.CommandArgs":{__getitem__:[0,2,1,""],joined:[0,2,1,""],match:[0,2,1,""],optional:[0,2,1,""]},"royalnet.commands.CommandData":{get_author:[0,2,1,""],reply:[0,2,1,""]},"royalnet.commands.CommandInterface":{alchemy:[0,3,1,""],bot:[0,3,1,""],loop:[0,3,1,""],name:[0,3,1,""],net_request:[0,2,1,""],prefix:[0,3,1,""],register_net_handler:[0,2,1,""],unregister_net_handler:[0,2,1,""]},"royalnet.database":{Alchemy:[0,1,1,""],DatabaseConfig:[0,1,1,""],relationshiplinkchain:[0,4,1,""]},"royalnet.database.Alchemy":{__init__:[0,2,1,""],_create_tables:[0,2,1,""],session_acm:[0,2,1,""],session_cm:[0,2,1,""]},"royalnet.error":{CurrentlyDisabledError:[0,5,1,""],ExternalError:[0,5,1,""],FileTooBigError:[0,5,1,""],InvalidConfigError:[0,5,1,""],InvalidInputError:[0,5,1,""],NoneFoundError:[0,5,1,""],RoyalnetRequestError:[0,5,1,""],RoyalnetResponseError:[0,5,1,""],TooManyFoundError:[0,5,1,""],UnregisteredError:[0,5,1,""],UnsupportedError:[0,5,1,""]},"royalnet.network":{ConnectionClosedError:[0,5,1,""],NetworkError:[0,5,1,""],NotConnectedError:[0,5,1,""],NotIdentifiedError:[0,5,1,""],Package:[0,1,1,""],Request:[0,1,1,""],Response:[0,1,1,""],ResponseError:[0,1,1,""],ResponseSuccess:[0,1,1,""],RoyalnetConfig:[0,1,1,""],RoyalnetLink:[0,1,1,""],RoyalnetServer:[0,1,1,""]},"royalnet.network.Package":{__init__:[0,2,1,""],from_dict:[0,2,1,""],from_json_bytes:[0,2,1,""],from_json_string:[0,2,1,""],reply:[0,2,1,""],to_dict:[0,2,1,""],to_json_bytes:[0,2,1,""],to_json_string:[0,2,1,""]},"royalnet.network.Request":{from_dict:[0,2,1,""],to_dict:[0,2,1,""]},"royalnet.network.Response":{from_dict:[0,2,1,""],raise_on_error:[0,2,1,""],to_dict:[0,2,1,""]},"royalnet.network.ResponseError":{raise_on_error:[0,2,1,""]},"royalnet.network.ResponseSuccess":{raise_on_error:[0,2,1,""]},"royalnet.network.RoyalnetLink":{connect:[0,2,1,""],identify:[0,2,1,""],receive:[0,2,1,""],request:[0,2,1,""],run:[0,2,1,""],send:[0,2,1,""]},"royalnet.network.RoyalnetServer":{find_client:[0,2,1,""],find_destination:[0,2,1,""],listener:[0,2,1,""],route_package:[0,2,1,""],serve:[0,2,1,""],start:[0,2,1,""]},"royalnet.utils":{NetworkHandler:[0,1,1,""],andformat:[0,4,1,""],asyncify:[0,4,1,""],cdj:[0,4,1,""],discord_escape:[0,4,1,""],fileformat:[0,4,1,""],numberemojiformat:[0,4,1,""],ordinalformat:[0,4,1,""],parse_5etools_entry:[0,4,1,""],plusformat:[0,4,1,""],safeformat:[0,4,1,""],sleep_until:[0,4,1,""],splitstring:[0,4,1,""],telegram_escape:[0,4,1,""],ytdldateformat:[0,4,1,""]},"royalnet.utils.NetworkHandler":{message_type:[0,3,1,""]},"royalnet.web":{Royalprint:[0,1,1,""],create_app:[0,4,1,""]},royalnet:{audio:[0,0,0,"-"],bots:[0,0,0,"-"],commands:[0,0,0,"-"],database:[0,0,0,"-"],error:[0,0,0,"-"],network:[0,0,0,"-"],utils:[0,0,0,"-"],web:[0,0,0,"-"]}},objnames:{"0":["py","module","Python module"],"1":["py","class","Python class"],"2":["py","method","Python method"],"3":["py","attribute","Python attribute"],"4":["py","function","Python function"],"5":["py","exception","Python exception"]},objtypes:{"0":"py:module","1":"py:class","2":"py:method","3":"py:attribute","4":"py:function","5":"py:exception"},terms:{"20m":0,"byte":0,"class":[0,1],"default":0,"final":0,"function":[0,1],"import":1,"int":0,"new":[0,2],"null":0,"return":0,"short":1,"static":0,"super":1,"true":0,"try":[0,1],"while":[0,1],And:1,That:0,The:[0,1],Then:[0,1],These:0,Use:0,__dict__:0,__doc__:0,__getitem__:0,__init__:[0,1],__module__:0,__slots__:0,__weakref__:0,_bot_factori:0,_create_t:0,_data_factori:0,_default_ytdl_arg:0,_handle_upd:0,_init_cli:0,_init_command:0,_init_databas:0,_init_royalnet:0,_init_voic:0,_interface_factori:0,_network_handl:0,abl:0,about:0,abstracteventloop:0,access:0,accur:0,add:0,add_to_music_data:0,added:[0,1],adding:[0,1],addit:0,address:0,advance_music_data:0,akin:0,alchemi:0,all:0,allow:[0,1],also:0,altern:0,alwai:0,amount:0,andformat:0,ani:[0,1],anoth:0,anymor:0,anystr:0,api:2,app:0,applic:0,arg:[0,1],argument:0,around:0,arrai:0,async:[0,1],asyncifi:[0,1],asyncio:[0,1],asyncron:0,attempt:0,attribut:[0,1],audio:2,audiosourc:0,author:0,autocomplet:0,automat:0,avail:0,avoid:1,await:1,base:0,becaus:1,been:0,befor:1,being:[0,1],between:0,big:0,block:0,blockingli:0,blueprint:0,bool:0,bot:[1,2],both:0,bufferediobas:0,bug:1,call:[0,1],callabl:0,can:[0,1],cancel:0,cannot:0,caus:1,caution:0,cdj:0,chain:0,chang:0,change_pres:0,channel:0,charact:0,chat:[0,1],check:0,class_:0,classmethod:0,client:0,close:0,clue:0,code:[0,1],command:2,commandarg:0,commanddata:[0,1],commandinterfac:0,commun:0,complet:0,compon:0,config:0,config_obj:0,configur:0,connect:0,connectedcli:0,connectionclosederror:0,consid:1,consum:0,contain:0,context:0,convers:0,convert:0,convert_to_mp3:0,convert_to_pcm:0,core:0,coroutin:[0,2],correctli:0,correspond:0,creat:[0,2],create_and_ready_from_url:0,create_app:0,create_from_url:0,current:0,currentlydisablederror:0,custom:0,dai:0,data:[0,1],databas:2,database_config:0,database_uri:0,databaseconfig:0,date:0,datetim:0,db_path:0,declar:0,def:1,delet:0,describ:0,descript:[0,1],destin:0,destination_conv_id:0,detail:0,dfile:0,dict:0,dictionari:0,disabl:0,discord:0,discord_config:0,discord_escap:0,discordbot:0,discordcli:0,discordconfig:0,displai:0,doc:0,docstr:0,document:2,doe:[0,1],doesn:0,don:[0,1],done:1,download:0,download_1_terabyte_of_spaghetti:1,download_fil:0,download_from_url:0,dynam:0,eas:0,edit:0,effect:1,either:0,element:0,emb:0,emoji:1,empti:0,encod:0,end:0,ending_class:0,engin:0,enough:1,ensur:0,entri:0,envvar:0,epoch:0,error:2,error_data:0,error_if_non:0,escap:0,even:0,event:0,everi:[0,1],everyth:0,exact:1,exampl:[0,1],except:0,execut:[0,1],exist:0,expect:0,ext:0,externalerror:0,extra_info:0,extract:0,extract_info:0,fals:0,featur:0,fetch:0,file:[0,1],fileaudiosourc:0,fileformat:0,filenam:0,filetoobigerror:0,find:0,find_client:0,find_destin:0,finish:1,first:1,flask:0,follow:0,format:0,found:0,from:[0,1],from_dict:0,from_json_byt:0,from_json_str:0,from_object:0,fullfil:0,gener:0,genericbot:0,get:0,get_author:0,github:2,greater:0,group:0,guild:0,handl:0,handler:0,has:[0,1],has_info:0,have:[0,1],how:0,html:0,http:0,identifi:0,identity_column_nam:0,identity_t:0,ifi:0,ignor:0,ignoreerror:0,imag:1,import_nam:0,incom:0,incomplet:0,index:[0,2],inf:0,info:0,inform:0,inherit:[0,1],initi:0,input:0,insid:1,instanc:0,instead:[0,1],interfac:[0,1],interface_nam:0,invalid:0,invalidconfigerror:0,invalidinputerror:0,is_download:0,is_opu:0,isn:[0,1],itali:1,item:0,join:0,json:0,jsonabl:0,just:[0,1],keep:1,kei:0,keyword:1,kind:1,kwarg:0,last:0,less:0,like:[0,1],link:0,link_typ:0,list:0,listen:0,login:0,look:[0,1],loop:0,made:0,mai:1,main:0,mainli:0,maintain:0,make:0,manag:0,markup:0,master_secret:0,master_t:0,master_uri:0,match:0,max:0,mean:0,meantim:1,memori:0,mention:1,messag:[0,1],message_typ:0,method:[0,1],middl:0,might:0,minimum:0,miscellan:0,miss:0,month:0,more:0,multipl:0,music_data:0,must:0,name:[0,1],need:0,net_request:0,network:2,network_handl:0,networkerror:0,networkhandl:0,next:[0,1],nid:0,no_warn:0,nobodi:0,node:0,non:0,none:0,nonefounderror:0,noplaylist:0,normal:1,notat:0,notconnectederror:0,noth:0,notic:1,notidentifiederror:0,notimpl:0,now:[0,1],number:0,numberemojiformat:0,object:0,offset:0,onc:[0,1],one:0,ones:0,onli:0,open:0,oper:2,option:0,optional_arg:0,opu:0,ordinalformat:0,org:0,other:[0,1],otherwis:0,outdat:0,output:0,outtmpl:0,overrid:1,packag:0,packet:0,page:0,paramet:0,parse_5etools_entri:0,part:1,pass:0,path:0,pattern:0,pcm:0,pcm_avail:0,pickl:0,ping:1,pingcommand:1,plai:[0,1],plusformat:0,pong:1,port:0,possibl:[0,1],prefix:0,prepar:0,prepend:0,presenc:0,previou:1,previous:1,probabl:0,properti:0,python:1,quiet:0,rais:0,raise_on_error:0,read:0,readi:1,ready_up:0,real:0,realli:0,receiv:[0,1],reciev:0,recreat:0,refer:2,regex:0,regist:0,register_net_handl:0,relat:0,relationshiplinkchain:0,remov:0,replac:0,repli:[0,1],request:0,request_dict:0,request_handl:0,requir:0,require_alchemy_t:0,require_at_least:0,required_arg:0,required_secret:0,required_t:0,respect:1,respons:0,responseerror:0,responsesuccess:0,rest:1,result:0,retriev:0,retrieve_for_url:0,right:0,right_now:1,root_path:0,rout:0,route_packag:0,row:[0,1],royalcod:0,royalnet:0,royalnet_config:0,royalnetconfig:0,royalnetlink:0,royalnetrequesterror:0,royalnetresponseerror:0,royalnetserv:0,royalprint:0,run:[0,1],safeformat:0,same:1,script:1,second:0,secret:0,secret_kei:0,select:0,self:[0,1],send:[0,1],sent:[0,1],sentry_dsn:0,separ:[0,1],sequenc:0,serv:0,server:0,session_acm:0,session_cm:0,set:0,should:[0,1],side:1,signal:0,simpl:1,singl:0,skip:0,sleep:1,sleep_until:0,slow:2,small:[0,1],someth:0,somewher:0,song:0,sourc:0,source_conv_id:0,space:0,spaghetti:1,spaghetticommand:1,spawn_audiosourc:0,special:1,specif:[0,1],specifi:0,splitstr:0,sqlalchemi:0,stai:1,start:[0,1],starting_class:0,statement:0,static_fold:0,static_url_path:0,statu:0,stop:1,store:0,str:0,stream:0,string:0,subdomain:0,submodul:0,success:0,support:0,syntax:0,tabl:0,task:0,telegram:0,telegram_config:0,telegram_escap:0,telegrambot:0,telegramconfig:0,tell:1,template_fold:0,temporar:0,text:0,than:0,thei:[0,1],them:0,therefor:0,thi:[0,1],thing:1,think:1,thought:1,through:0,time:[0,1],titl:0,to_dict:0,to_discord_emb:0,to_json_byt:0,to_json_str:0,token:0,too:0,toomanyfounderror:0,tupl:0,two:0,type:[0,1],underscor:0,undescrib:0,unexpect:0,unexpectedli:0,union:0,unregister_net_handl:0,unregisterederror:0,unsupportederror:0,until:[0,1],updat:0,update_activity_with_source_titl:0,update_info:0,uri:0,url:0,url_default:0,url_prefix:0,use:[0,1],used:0,useful:0,user:0,uses:0,using:[0,1],usual:0,utf8:0,util:[1,2],uuid:0,valid:0,valu:0,variabl:0,variou:0,video:0,voic:0,wai:0,wait:0,want:[0,1],web:2,websocket:0,websocketserverprotocol:0,weird:0,welcom:2,went:0,were:0,what:1,when:[0,1],whenev:1,where:0,which:0,why:0,without:0,word:0,work:[0,1],worth:0,would:0,wrap:1,wrapper:0,written:0,wrong:0,wrote:1,year:0,yet:0,you:[0,1],your:1,youtub:0,youtube_dl:0,youtubedl:0,ytdl_arg:0,ytdl_file:0,ytdldateformat:0,ytdldiscord:0,ytdlfile:0,ytdlinfo:0,ytdlmp3:0,yyyi:0,yyyymmdd:0},titles:["API Reference","Royalnet Commands","royalnet"],titleterms:{"new":1,api:0,audio:0,bot:0,command:[0,1],coroutin:1,creat:1,databas:0,error:0,link:2,network:0,oper:1,refer:0,royalnet:[1,2],slow:1,some:2,useful:2,util:0,web:0}})
\ No newline at end of file
diff --git a/docs_source/creatingacommand.rst b/docs_source/creatingacommand.rst
index 341e2437..e617e69f 100644
--- a/docs_source/creatingacommand.rst
+++ b/docs_source/creatingacommand.rst
@@ -22,7 +22,6 @@ A Command code looks like this: ::
# This code is run every time the command is called
await data.reply("Pong!")
-
Creating a new Command
------------------------------------
@@ -33,7 +32,7 @@ Try to keep the name as short as possible, while staying specific enough so no o
Next, create a new Python file with the ``name`` you have thought of.
The previously mentioned "spaghetti" command should have a file called ``spaghetti.py``.
-Then, in the first row of the file, import the :py:class:`Command` class from :py:mod:`royalnet`, and create a new class inheriting from it: ::
+Then, in the first row of the file, import the :py:class:`Command` class from royalnet, and create a new class inheriting from it: ::
from royalnet.commands import Command
@@ -61,6 +60,36 @@ To send a message in the chat the command was called in, you can use the :py:met
description = "Send a spaghetti emoji in the chat."
async def run(self, args, data):
- data.reply("๐")
+ await data.reply("๐")
-And it's done! The command is now ready to be used in a bot!
+And... it's done! The command is ready to be added to a bot!
+
+Coroutines and slow operations
+------------------------------------
+
+You may have noticed that in the previous example I wrote ``await data.reply("๐")`` instead of just ``data.reply("๐")``.
+
+This is because :py:meth:`CommandData.reply` isn't a simple method: it is a coroutine, a special kind of function that
+ can be executed separately from the rest of the code, allowing the bot to do other things in the meantime.
+
+By adding the ``await`` keyword before the ``data.reply("๐")``, we tell the bot that it can do other things, like
+ receiving new messages, while the message is being sent.
+
+You should avoid running slow normal functions inside bot commands, as they will stop the bot from working until they
+ are finished and may cause bugs in other parts of the code! ::
+
+ async def run(self, args, data):
+ # Don't do this!
+ image = download_1_terabyte_of_spaghetti("right_now", from="italy")
+ ...
+
+If the slow function you want does not cause any side effect, you can wrap it with the :ref:`royalnet.utils.asyncify`
+ function: ::
+
+ async def run(self, args, data):
+ # If the called function has no side effect, you can do this!
+ image = await asyncify(download_1_terabyte_of_spaghetti, "right_now", from="italy")
+ ...
+
+Avoid using :py:func:`time.sleep` function, as it is considered a slow operation: use instead :py:func:`asyncio.sleep`,
+ a coroutine that does the same exact thing.