diff --git a/docs/doctrees/creatingacommand.doctree b/docs/doctrees/creatingacommand.doctree index 185af670..8d27a778 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 bcf19274..1fbd013d 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 3cbcc681..dab1a02a 100644 --- a/docs/html/_sources/creatingacommand.rst.txt +++ b/docs/html/_sources/creatingacommand.rst.txt @@ -166,7 +166,7 @@ To match a pattern, :py:func:`re.match` is used, meaning that Python will try to # ("carbonara", "al-dente") Running code at the initialization of the bot ------------------------------------- +--------------------------------------------- You can run code while the bot is starting by overriding the :py:meth:`Command.__init__` function. @@ -229,14 +229,102 @@ function: :: 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. -Accessing the database +Using the database ------------------------------------ -.. Usually, bots are connected to a PostgreSQL database through a :py:class:`royalnet.database.Alchemy` interface (which is -itself a SQLAlchemy wrapper). +Bots can be connected to a PostgreSQL database through a special SQLAlchemy interface called +:py:class:`royalnet.database.Alchemy`. -.. Commands can access the connected database through the :py:class:`royalnet.database.Alchemy` available at -``self.interface.alchemy``, and can access the database session at ``self.interface.session``. +If the connection is established, the ``self.interface.alchemy`` and ``self.interface.session`` fields will be +available for use in commands. + +``self.interface.alchemy`` is an instance of :py:class:`royalnet.database.Alchemy`, which contains the +:py:class:`sqlalchemy.engine.Engine`, metadata and tables, while ``self.interface.session`` is a +:py:class:`sqlalchemy.orm.session.Session`, and can be interacted in the same way as one. + +If you want to use :py:class:`royalnet.database.Alchemy` in your command, you should override the +``require_alchemy_tables`` field with the :py:class:`set` of Alchemy tables you need. :: + + from royalnet.commands import Command + from royalnet.database.tables import Royal + + class SpaghettiCommand(Command): + name = "spaghetti" + + description = "Send a spaghetti emoji in the chat." + + syntax = "(pasta)" + + requrire_alchemy_tables = {Royal} + + ... + +Querying the database +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can :py:class:`sqlalchemy.orm.query.Query` the database using the SQLAlchemy ORM. + +The SQLAlchemy tables can be found inside :py:class:`royalnet.database.Alchemy` with the same name they were created +from, if they were specified in ``require_alchemy_tables``. :: + + RoyalTable = self.interface.alchemy.Royal + query = self.interface.session.query(RoyalTable) + +Adding filters to the query +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can filter the query results with the :py:meth:`sqlalchemy.orm.query.Query.filter` method. + +.. note:: Remember to always use a table column as first comparision element, as it won't work otherwise. + +:: + + query = query.filter(RoyalTable.role == "Member") + + +Ordering the results of a query +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can order the query results in **ascending order** with the :py:meth:`sqlalchemy.orm.query.Query.order_by` method. :: + + query = query.order_by(RoyalTable.username) + +Additionally, you can append the `.desc()` method to a table column to sort in **descending order**: :: + + query = query.order_by(RoyalTable.username.desc()) + +Fetching the results of a query +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can fetch the query results with the :py:meth:`sqlalchemy.orm.query.Query.all`, +:py:meth:`sqlalchemy.orm.query.Query.first`, :py:meth:`sqlalchemy.orm.query.Query.one` and +:py:meth:`sqlalchemy.orm.query.Query.one_or_none` methods. + +Remember to use :py:func:`royalnet.utils.asyncify` when fetching results, as it may take a while! + +Use :py:meth:`sqlalchemy.orm.query.Query.all` if you want a :py:class:`list` of **all results**: :: + + results: list = await asyncify(query.all) + +Use :py:meth:`sqlalchemy.orm.query.Query.first` if you want **the first result** of the list, or :py:const:`None` if +there are no results: :: + + result: typing.Union[..., None] = await asyncify(query.first) + +Use :py:meth:`sqlalchemy.orm.query.Query.one` if you expect to have **a single result**, and you want the command to +raise an error if any different number of results is returned: :: + + result: ... = await asyncify(query.one) # Raises an error if there are no results or more than a result. + +Use :py:meth:`sqlalchemy.orm.query.Query.one_or_none` if you expect to have **a single result**, or **nothing**, and +if you want the command to raise an error if the number of results is greater than one. :: + + result: typing.Union[..., None] = await asyncify(query.one_or_none) # Raises an error if there is more than a result. + +More Alchemy +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can read more about :py:mod:`sqlalchemy` at their `website `_. Comunicating via Royalnet ------------------------------------ diff --git a/docs/html/apireference.html b/docs/html/apireference.html index 5cff7a9f..53f3ee95 100644 --- a/docs/html/apireference.html +++ b/docs/html/apireference.html @@ -383,7 +383,7 @@
_init_client()
-

Create the telegram.Bot, and set the starting offset.

+

Create the telegram.Bot, and set the starting offset.

diff --git a/docs/html/creatingacommand.html b/docs/html/creatingacommand.html index 94b99b0e..17567d4b 100644 --- a/docs/html/creatingacommand.html +++ b/docs/html/creatingacommand.html @@ -93,7 +93,14 @@
  • Running code at the initialization of the bot
  • Coroutines and slow operations
  • -
  • Accessing the database
  • +
  • Using the database +
  • Comunicating via Royalnet
  • @@ -371,10 +378,94 @@ function:

    Avoid using time.sleep() function, as it is considered a slow operation: use instead asyncio.sleep(), a coroutine that does the same exact thing.

    -
    -

    Accessing the database

    -

    itself a SQLAlchemy wrapper).

    -

    self.interface.alchemy, and can access the database session at self.interface.session.

    +
    +

    Using the database

    +

    Bots can be connected to a PostgreSQL database through a special SQLAlchemy interface called +royalnet.database.Alchemy.

    +

    If the connection is established, the self.interface.alchemy and self.interface.session fields will be +available for use in commands.

    +

    self.interface.alchemy is an instance of royalnet.database.Alchemy, which contains the +sqlalchemy.engine.Engine, metadata and tables, while self.interface.session is a +sqlalchemy.orm.session.Session, and can be interacted in the same way as one.

    +

    If you want to use royalnet.database.Alchemy in your command, you should override the +require_alchemy_tables field with the set of Alchemy tables you need.

    +
    from royalnet.commands import Command
    +from royalnet.database.tables import Royal
    +
    +class SpaghettiCommand(Command):
    +    name = "spaghetti"
    +
    +    description = "Send a spaghetti emoji in the chat."
    +
    +    syntax = "(pasta)"
    +
    +    requrire_alchemy_tables = {Royal}
    +
    +    ...
    +
    +
    +
    +

    Querying the database

    +

    You can sqlalchemy.orm.query.Query the database using the SQLAlchemy ORM.

    +

    The SQLAlchemy tables can be found inside royalnet.database.Alchemy with the same name they were created +from, if they were specified in require_alchemy_tables.

    +
    RoyalTable = self.interface.alchemy.Royal
    +query = self.interface.session.query(RoyalTable)
    +
    +
    +
    +
    +

    Adding filters to the query

    +

    You can filter the query results with the sqlalchemy.orm.query.Query.filter() method.

    +
    +

    Note

    +

    Remember to always use a table column as first comparision element, as it won’t work otherwise.

    +
    +
    query = query.filter(RoyalTable.role == "Member")
    +
    +
    +
    +
    +

    Ordering the results of a query

    +

    You can order the query results in ascending order with the sqlalchemy.orm.query.Query.order_by() method.

    +
    query = query.order_by(RoyalTable.username)
    +
    +
    +

    Additionally, you can append the .desc() method to a table column to sort in descending order:

    +
    query = query.order_by(RoyalTable.username.desc())
    +
    +
    +
    +
    +

    Fetching the results of a query

    +

    You can fetch the query results with the sqlalchemy.orm.query.Query.all(), +sqlalchemy.orm.query.Query.first(), sqlalchemy.orm.query.Query.one() and +sqlalchemy.orm.query.Query.one_or_none() methods.

    +

    Remember to use royalnet.utils.asyncify() when fetching results, as it may take a while!

    +

    Use sqlalchemy.orm.query.Query.all() if you want a list of all results:

    +
    results: list = await asyncify(query.all)
    +
    +
    +

    Use sqlalchemy.orm.query.Query.first() if you want the first result of the list, or None if +there are no results:

    +
    result: typing.Union[..., None] = await asyncify(query.first)
    +
    +
    +

    Use sqlalchemy.orm.query.Query.one() if you expect to have a single result, and you want the command to +raise an error if any different number of results is returned:

    +
    result: ... = await asyncify(query.one)  # Raises an error if there are no results or more than a result.
    +
    +
    +

    Use sqlalchemy.orm.query.Query.one_or_none() if you expect to have a single result, or nothing, and +if you want the command to raise an error if the number of results is greater than one.

    +
    result: typing.Union[..., None] = await asyncify(query.one_or_none)  # Raises an error if there is more than a result.
    +
    +
    +
    +
    +

    More Alchemy

    +

    You can read more about sqlalchemy at their website.

    +

    Comunicating via Royalnet

    diff --git a/docs/html/index.html b/docs/html/index.html index b0cb249f..6ff10692 100644 --- a/docs/html/index.html +++ b/docs/html/index.html @@ -163,7 +163,14 @@
  • Running code at the initialization of the bot
  • Coroutines and slow operations
  • -
  • Accessing the database
  • +
  • Using the database +
  • Comunicating via Royalnet
  • diff --git a/docs/html/searchindex.js b/docs/html/searchindex.js index 9ac17acb..16ced4a4 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,1],"final":0,"function":[0,1],"import":1,"int":0,"new":[0,2],"null":0,"return":[0,1],"short":1,"static":[0,1],"super":1,"true":0,"try":[0,1],"while":[0,1],And:1,For:1,That:0,The:[0,1],Then:[0,1],These:[0,1],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,2],accur:0,add:[0,1],add_to_music_data:0,added:[0,1],adding:[0,1],addit:0,address:0,advance_music_data:0,after:1,akin:0,alchemi:[0,1],all:[0,1],allow:[0,1],alreadi:1,also:0,altern:0,alwai:0,amount:0,andformat:0,ani:[0,1],anoth:0,anymor:0,anystr:0,api:2,app:0,append:1,applic:0,arg:[0,1],argument:[0,2],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,banana:1,base:0,becaus:1,been:0,befor:1,begin:1,being:[0,1],between:[0,1],big:0,block:0,blockingli:0,blueprint:0,bool:0,bot:2,both:0,bracket:1,brief:1,bufferediobas:0,bug:1,call:[0,1],callabl:0,can:[0,1],cancel:0,cannot:0,carb:1,carbonara:1,caus:1,caution:0,cdj:0,certain:1,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,2],command:2,commandarg:[0,1],commanddata:[0,1],commandinterfac:0,commun:0,complet:0,complex:1,compon:0,comun:2,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,dent:1,describ:0,descript:[0,1],destin:0,destination_conv_id:0,detail:0,dfile:0,dict:0,dictionari:0,direct:2,directli:1,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:[1,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,1],expect:0,express:2,ext:0,extern:1,externalerror:0,extra_info:0,extract:0,extract_info:0,fals:0,featur:0,fetch:[0,1],field:1,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,full:2,fullfil:0,gener:0,genericbot:0,get:[0,1],get_author:0,github:2,greater:0,group:[0,1],guild:0,handl:0,handler:0,has:[0,1],has_info:0,have:[0,1],here: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,2],input:0,insid:1,instanc:[0,1],instead:[0,1],interfac:[0,1],interface_nam:0,invalid:0,invalidconfigerror:0,invalidinputerror:[0,1],is_download:0,is_opu:0,isn:[0,1],itali:1,item:0,itself:1,join:[0,1],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,1],listen:0,login:0,look:[0,1],loop:0,made:0,mai:1,main:0,mainli:0,maintain:0,make:[0,1],manag:0,markup:0,master_secret:0,master_t:0,master_uri:0,match:[0,1],max:0,mean:[0,1],meantim:1,memori:0,mention:1,messag:[0,1],message_typ:0,method:[0,1],middl:0,might:0,minimum:[0,1],miscellan:0,miss:0,month:0,more:[0,1],multipl:[0,1],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,1],nonefounderror:0,noplaylist:0,normal:1,notat:0,notconnectederror:0,noth:0,notic:1,notidentifiederror:0,notimpl:0,now:[0,1],number:[0,1],numberemojiformat:0,object:[0,1],offset:0,onc:[0,1],one:0,ones:[0,1],onli:[0,1],open:0,oper:2,option:[0,2],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,1],parenthes:1,parse_5etools_entri:0,part:1,pass:[0,1],pasta:1,path:0,pattern:[0,1],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,present:1,previou:1,previous:1,probabl:0,properli:1,properti:0,python:1,quiet:0,rais:[0,1],raise_on_error:0,read:0,readi:1,ready_up:0,real:0,realli:0,receiv:[0,1],reciev:0,recreat:0,refer:[1,2],regex:0,regist:0,register_net_handl:0,regular:2,relat:0,relationshiplinkchain:0,remov:0,replac:0,repli:[0,1],request:[0,1],request_dict:0,request_handl:0,requested_pasta:1,requestedpasta:1,requir:[0,1],require_alchemy_t:0,require_at_least:[0,1],required_arg:0,required_secret:0,required_t:0,respect:1,respons:0,responseerror:0,responsesuccess:0,rest:1,restart:1,result:[0,1],retriev:0,retrieve_for_url:0,right:0,right_now:1,root_path:0,round:1,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,2],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:1,session_acm:0,session_cm:0,set:0,share:1,should:[0,1],side:1,signal:0,simpl:1,singl:0,skip:0,sleep:1,sleep_until:0,slow:2,small:[0,1],some:1,someth:0,somewher:0,song:0,sourc:0,source_conv_id:0,space:[0,1],spaghetti:1,spaghetticommand:1,spawn_audiosourc:0,special:1,specif:[0,1],specifi:[0,1],splitstr:0,sqlalchemi:[0,1],squar:1,stai:1,start:[0,1],starting_class:0,statement:0,static_fold:0,static_url_path:0,statu:0,stop:1,store:[0,1],str:[0,1],stream:0,string:[0,2],subdomain:0,submodul:0,success:0,support:0,syntax:[0,1],tabl:0,task:[0,1],telegram:[0,1],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,1],therefor:0,thi:[0,1],thing:1,think:1,thought:1,through:[0,1],time:[0,1],titl:0,to_dict:0,to_discord_emb:0,to_json_byt:0,to_json_str:0,token:0,too:[0,1],toomanyfounderror:0,tri:1,tupl:[0,1],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,1],useful:[0,1],user:[0,1],uses:0,using:[0,1],usual:0,utf8:0,util:[1,2],uuid:0,valid:0,valu:0,variabl:0,variou:0,via:2,video:0,voic:0,wai:[0,1],wait:0,want:[0,1],wasn:1,web:2,websocket:0,websocketserverprotocol:0,weird:0,welcom:2,went:0,were:[0,1],what:1,when:[0,1],whenev:1,where:0,which:[0,1],why:0,without:0,word:0,work:[0,1],worth:0,would:0,wrap:1,wrapper:[0,1],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,access:1,api:0,argument:1,audio:0,bot:[0,1],code:1,command:[0,1],comun:1,coroutin:1,creat:1,databas:[0,1],direct:1,error:0,express:1,full:1,initi:1,link:2,network:0,oper:1,option:1,refer:0,regular:1,royalnet:[1,2],run:1,slow:1,some:2,string:1,useful:2,util:0,via:1,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,1],"final":0,"function":[0,1],"import":1,"int":0,"new":[0,2],"null":0,"return":[0,1],"short":1,"static":[0,1],"super":1,"true":0,"try":[0,1],"while":[0,1],Adding:2,And:1,For:1,That:0,The:[0,1],Then:[0,1],These:[0,1],Use:[0,1],Using:2,__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,1],abstracteventloop:0,access:[0,2],accur:0,add:[0,1],add_to_music_data:0,added:[0,1],adding:[0,1],addit:0,addition:1,address:0,advance_music_data:0,after:1,akin:0,alchemi:[0,2],all:[0,1],allow:[0,1],alreadi:1,also:0,altern:0,alwai:[0,1],amount:0,andformat:0,ani:[0,1],anoth:0,anymor:0,anystr:0,api:2,app:0,append:1,applic:0,arg:[0,1],argument:[0,2],around:0,arrai:0,ascend:1,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,1],avoid:1,await:1,banana:1,base:0,becaus:1,been:0,befor:1,begin:1,being:[0,1],between:[0,1],big:0,block:0,blockingli:0,blueprint:0,bool:0,bot:2,both:0,bracket:1,brief:1,bufferediobas:0,bug:1,call:[0,1],callabl:0,can:[0,1],cancel:0,cannot:0,carb:1,carbonara:1,caus:1,caution:0,cdj:0,certain:1,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,2],column:1,command:2,commandarg:[0,1],commanddata:[0,1],commandinterfac:0,commun:0,comparis:1,complet:0,complex:1,compon:0,comun:2,config:0,config_obj:0,configur:0,connect:[0,1],connectedcli:0,connectionclosederror:0,consid:1,consum:0,contain:[0,1],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,dent:1,desc:1,descend:1,describ:0,descript:[0,1],destin:0,destination_conv_id:0,detail:0,dfile:0,dict:0,dictionari:0,differ:1,direct:2,directli:1,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,1],emb:0,emoji:1,empti:0,encod:0,end:0,ending_class:0,engin:[0,1],enough:1,ensur:0,entri:0,envvar:0,epoch:0,error:[1,2],error_data:0,error_if_non:0,escap:0,establish:1,even:0,event:0,everi:[0,1],everyth:0,exact:1,exampl:[0,1],except:0,execut:[0,1],exist:[0,1],expect:[0,1],express:2,ext:0,extern:1,externalerror:0,extra_info:0,extract:0,extract_info:0,fals:0,featur:0,fetch:[0,2],field:1,file:[0,1],fileaudiosourc:0,fileformat:0,filenam:0,filetoobigerror:0,filter:2,find:0,find_client:0,find_destin:0,finish:1,first:1,flask:0,follow:0,format:0,found:[0,1],from:[0,1],from_dict:0,from_json_byt:0,from_json_str:0,from_object:0,full:2,fullfil:0,gener:0,genericbot:0,get:[0,1],get_author:0,github:2,greater:[0,1],group:[0,1],guild:0,handl:0,handler:0,has:[0,1],has_info:0,have:[0,1],here: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,2],input:0,insid:1,instanc:[0,1],instead:[0,1],interact:1,interfac:[0,1],interface_nam:0,invalid:0,invalidconfigerror:0,invalidinputerror:[0,1],is_download:0,is_opu:0,isn:[0,1],itali:1,item:0,join:[0,1],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,1],listen:0,login:0,look:[0,1],loop:0,made:0,mai:1,main:0,mainli:0,maintain:0,make:[0,1],manag:0,markup:0,master_secret:0,master_t:0,master_uri:0,match:[0,1],max:0,mean:[0,1],meantim:1,member:1,memori:0,mention:1,messag:[0,1],message_typ:0,metadata:1,method:[0,1],middl:0,might:0,minimum:[0,1],miscellan:0,miss:0,month:0,more:[0,2],multipl:[0,1],music_data:0,must:0,name:[0,1],need:[0,1],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,1],nonefounderror:0,noplaylist:0,normal:1,notat:0,notconnectederror:0,noth:[0,1],notic:1,notidentifiederror:0,notimpl:0,now:[0,1],number:[0,1],numberemojiformat:0,object:[0,1],offset:0,onc:[0,1],one:[0,1],one_or_non:1,ones:[0,1],onli:[0,1],open:0,oper:2,option:[0,2],optional_arg:0,opu:0,order:2,order_bi:1,ordinalformat:0,org:0,orm:1,other:[0,1],otherwis:[0,1],outdat:0,output:0,outtmpl:0,overrid:1,packag:0,packet:0,page:0,paramet:[0,1],parenthes:1,parse_5etools_entri:0,part:1,pass:[0,1],pasta:1,path:0,pattern:[0,1],pcm:0,pcm_avail:0,pickl:0,ping:1,pingcommand:1,plai:[0,1],plusformat:0,pong:1,port:0,possibl:[0,1],postgresql:1,prefix:0,prepar:0,prepend:0,presenc:0,present:1,previou:1,previous:1,probabl:0,properli:1,properti:0,python:1,queri:2,quiet:0,rais:[0,1],raise_on_error:0,read:[0,1],readi:1,ready_up:0,real:0,realli:0,receiv:[0,1],reciev:0,recreat:0,refer:[1,2],regex:0,regist:0,register_net_handl:0,regular:2,relat:0,relationshiplinkchain:0,rememb:1,remov:0,replac:0,repli:[0,1],request:[0,1],request_dict:0,request_handl:0,requested_pasta:1,requestedpasta:1,requir:[0,1],require_alchemy_t:[0,1],require_at_least:[0,1],required_arg:0,required_secret:0,required_t:0,requrire_alchemy_t:1,respect:1,respons:0,responseerror:0,responsesuccess:0,rest:1,restart:1,result:[0,2],retriev:0,retrieve_for_url:0,right:0,right_now:1,role:1,root_path:0,round:1,rout:0,route_packag:0,row:[0,1],royal:1,royalcod:0,royalnet:0,royalnet_config:0,royalnetconfig:0,royalnetlink:0,royalnetrequesterror:0,royalnetresponseerror:0,royalnetserv:0,royalprint:0,royalt:1,run:[0,2],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:1,session_acm:0,session_cm:0,set:[0,1],share:1,should:[0,1],side:1,signal:0,simpl:1,singl:[0,1],skip:0,sleep:1,sleep_until:0,slow:2,small:[0,1],some:1,someth:0,somewher:0,song:0,sort:1,sourc:0,source_conv_id:0,space:[0,1],spaghetti:1,spaghetticommand:1,spawn_audiosourc:0,special:1,specif:[0,1],specifi:[0,1],splitstr:0,sqlalchemi:[0,1],squar:1,stai:1,start:[0,1],starting_class:0,statement:0,static_fold:0,static_url_path:0,statu:0,stop:1,store:[0,1],str:[0,1],stream:0,string:[0,2],subdomain:0,submodul:0,success:0,support:0,syntax:[0,1],tabl:[0,1],take:1,task:[0,1],telegram:[0,1],telegram_config:0,telegram_escap:0,telegrambot:0,telegramconfig:0,tell:1,template_fold:0,temporar:0,text:0,than:[0,1],thei:[0,1],them:[0,1],therefor:0,thi:[0,1],thing:1,think:1,thought:1,through:[0,1],time:[0,1],titl:0,to_dict:0,to_discord_emb:0,to_json_byt:0,to_json_str:0,token:0,too:[0,1],toomanyfounderror:0,tri:1,tupl:[0,1],two:0,type:[0,1],underscor:0,undescrib:0,unexpect:0,unexpectedli:0,union:[0,1],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,1],useful:[0,1],user:[0,1],usernam:1,uses:0,using:[0,1],usual:0,utf8:0,util:[1,2],uuid:0,valid:0,valu:0,variabl:0,variou:0,via:2,video:0,voic:0,wai:[0,1],wait:0,want:[0,1],wasn:1,web:2,websit:1,websocket:0,websocketserverprotocol:0,weird:0,welcom:2,went:0,were:[0,1],what:1,when:[0,1],whenev:1,where:0,which:[0,1],why:0,without:0,won:1,word:0,work:[0,1],worth:0,would:0,wrap:1,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,Adding:1,Using:1,access:1,alchemi:1,api:0,argument:1,audio:0,bot:[0,1],code:1,command:[0,1],comun:1,coroutin:1,creat:1,databas:[0,1],direct:1,error:0,express:1,fetch:1,filter:1,full:1,initi:1,link:2,more:1,network:0,oper:1,option:1,order:1,queri:1,refer:0,regular:1,result:1,royalnet:[1,2],run:1,slow:1,some:2,string:1,useful:2,util:0,via:1,web:0}}) \ No newline at end of file diff --git a/docs_source/creatingacommand.rst b/docs_source/creatingacommand.rst index 3cbcc681..dab1a02a 100644 --- a/docs_source/creatingacommand.rst +++ b/docs_source/creatingacommand.rst @@ -166,7 +166,7 @@ To match a pattern, :py:func:`re.match` is used, meaning that Python will try to # ("carbonara", "al-dente") Running code at the initialization of the bot ------------------------------------- +--------------------------------------------- You can run code while the bot is starting by overriding the :py:meth:`Command.__init__` function. @@ -229,14 +229,102 @@ function: :: 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. -Accessing the database +Using the database ------------------------------------ -.. Usually, bots are connected to a PostgreSQL database through a :py:class:`royalnet.database.Alchemy` interface (which is -itself a SQLAlchemy wrapper). +Bots can be connected to a PostgreSQL database through a special SQLAlchemy interface called +:py:class:`royalnet.database.Alchemy`. -.. Commands can access the connected database through the :py:class:`royalnet.database.Alchemy` available at -``self.interface.alchemy``, and can access the database session at ``self.interface.session``. +If the connection is established, the ``self.interface.alchemy`` and ``self.interface.session`` fields will be +available for use in commands. + +``self.interface.alchemy`` is an instance of :py:class:`royalnet.database.Alchemy`, which contains the +:py:class:`sqlalchemy.engine.Engine`, metadata and tables, while ``self.interface.session`` is a +:py:class:`sqlalchemy.orm.session.Session`, and can be interacted in the same way as one. + +If you want to use :py:class:`royalnet.database.Alchemy` in your command, you should override the +``require_alchemy_tables`` field with the :py:class:`set` of Alchemy tables you need. :: + + from royalnet.commands import Command + from royalnet.database.tables import Royal + + class SpaghettiCommand(Command): + name = "spaghetti" + + description = "Send a spaghetti emoji in the chat." + + syntax = "(pasta)" + + requrire_alchemy_tables = {Royal} + + ... + +Querying the database +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can :py:class:`sqlalchemy.orm.query.Query` the database using the SQLAlchemy ORM. + +The SQLAlchemy tables can be found inside :py:class:`royalnet.database.Alchemy` with the same name they were created +from, if they were specified in ``require_alchemy_tables``. :: + + RoyalTable = self.interface.alchemy.Royal + query = self.interface.session.query(RoyalTable) + +Adding filters to the query +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can filter the query results with the :py:meth:`sqlalchemy.orm.query.Query.filter` method. + +.. note:: Remember to always use a table column as first comparision element, as it won't work otherwise. + +:: + + query = query.filter(RoyalTable.role == "Member") + + +Ordering the results of a query +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can order the query results in **ascending order** with the :py:meth:`sqlalchemy.orm.query.Query.order_by` method. :: + + query = query.order_by(RoyalTable.username) + +Additionally, you can append the `.desc()` method to a table column to sort in **descending order**: :: + + query = query.order_by(RoyalTable.username.desc()) + +Fetching the results of a query +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can fetch the query results with the :py:meth:`sqlalchemy.orm.query.Query.all`, +:py:meth:`sqlalchemy.orm.query.Query.first`, :py:meth:`sqlalchemy.orm.query.Query.one` and +:py:meth:`sqlalchemy.orm.query.Query.one_or_none` methods. + +Remember to use :py:func:`royalnet.utils.asyncify` when fetching results, as it may take a while! + +Use :py:meth:`sqlalchemy.orm.query.Query.all` if you want a :py:class:`list` of **all results**: :: + + results: list = await asyncify(query.all) + +Use :py:meth:`sqlalchemy.orm.query.Query.first` if you want **the first result** of the list, or :py:const:`None` if +there are no results: :: + + result: typing.Union[..., None] = await asyncify(query.first) + +Use :py:meth:`sqlalchemy.orm.query.Query.one` if you expect to have **a single result**, and you want the command to +raise an error if any different number of results is returned: :: + + result: ... = await asyncify(query.one) # Raises an error if there are no results or more than a result. + +Use :py:meth:`sqlalchemy.orm.query.Query.one_or_none` if you expect to have **a single result**, or **nothing**, and +if you want the command to raise an error if the number of results is greater than one. :: + + result: typing.Union[..., None] = await asyncify(query.one_or_none) # Raises an error if there is more than a result. + +More Alchemy +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can read more about :py:mod:`sqlalchemy` at their `website `_. Comunicating via Royalnet ------------------------------------