- Config
- change the values of
config.json- If you don't have a
service_idor prefer to use a newservice_id, make it empty. - For
db_config, currently two types of configurations are supported: json and redis. For json you need to specifytype: "json" androot_diras your root directory to save the database files. For redis you need to specifytype: redis andpasswordfor your redis password.
- If you don't have a
- Run
python src/demo.py. It creates aDemoAgentobject and run the service. It is a simple forwarding service with one test button. If the service run successfully, you will find a button on the "keyboard" panel and every message you send will be repeated.
-
If you want to modify the code and start your own agent, please refer to the source code of
demo_agent.py. Basically, you need to write a subclass ofMoobiusAgentand implement all theon_xxx()methods. There is a trivial noop implementation inmoobius_agent.pywith does nothing but printing the messages to the console, and the code indemo_agent.pycould help you understand how it works. -
There are a bunch of helper methods for you to use. For an instance
agentofMoobiusAgentclass, you can use the following methods:agent.send_xxx(). These are higher level methods for you to send messages through websockets. These are defined in its parent classMoobiusBasicAgent. Please seesrc/moobius/moobius_basic_agent.pyagent.http_api.*(). These are wrapped HTTP APIs you may occasionally use. Please seesrc/moobius/basic/http_api_wrapper.py.agent.db_helper.*(). These are database-related operations commonly used.agent._ws_client.*(). These are low-level websocket APIs. You are not recommended to call them directly. The methods are defined insrc/moobius/basic/ws_client.py.agent.*()defined inMoobiusAgent. These are high-level complex operations that could involve multiple API calls or database operations. There could be more! Please seesrc/moobius/moobius_agent.py
moobius/basic: Basic utilites
http_api_wrapper.py: a pure implementation of low-level HTTP APIs.ws_message_builder.py: a pure builder of websocket API messages.ws_client.py: a websocket client based onwebsocketsthat facilitates automatic reconnection, exception handling andasyncio.create_task()wrapper (so that you can simply useawaitin higher methods.)
moobius/database: Database interface with commonly used operations
database_helper.py: The parent class that defines high-level methods (implemented) and low-level methods (not implemented) of database operations. All subclasses should implement all the low-level methods.json_helper.py: JSON implementationredis_helper.py: redis implementation
moobius/moobius_basic_agent.py: The Base class of a Service. It has a minimal but complete implementation of a fully functional Moobius Service instance (so that it is runnable!), including authentication, automatic heartbeat and a trivial handler to messages (print and noops).
moobius/moobius_agent.py: A Service with a built-in database helper (you can set it None), and some high level methods. It is highly recommended that your custom class inherit MoobiusAgent defined here.
It involves some trick to build a dict-like MagicalStorage with automatic DB sync (including sync after restart) independent of database implementation, and customizable domains (you can add custom attributes as needed).
moobius/basic/types.py
- Dataclasses are defined(
Character,Stage, etc).
moobius/dbtools
-
CachedDictis a dictionary with a database under the hood, and the changes in the dict will be automatically synchronized to the database. -
An abstract class
DatabaseInterfaceis defined indatabase_interface.py. As long as the methods defined in the interface are implemented (for a key-value pair), the instance of the concrete class can be used to initialize aCachedDictinstance. -
A functional JSON implementation is defined in
simple_json_database.py. You are welcome to make redis, MySQL, SQLite or other implementations. -
magical_storage.pyhas a classMagicalStoragebuilt onCachedDict, which supports customized on-the-flyCachedDictcontainers (put()) which can automatically load (load=True) from a database on initialization, or automatically clear the database (clear=True) to clean out garbage records.
run python demo_magic.py for demo.
Define them!
- Database related refactoring, documentations, etc
- Detailed websocket messages (channel_info, etc)
- Non-blocking operations after
start()(multiprocessing) - Async http and database
- Auto refresh tokens!
- Tutorials
- Database safety (lots of work)
- Data Types!
================================ OLD VERSION ====================================
Run start_tmux_session.sh, which start redis server and run main.py. If something goes wrong, you could tmux attach -t to the session and check the error log.
Run scourgify.sh, which will delete all the keys except service_id in the database.
Please copy sample_config.py and name it as config.py, then fill up the data fields.
If it is the first time you are running main.py, you need to create a service and bind it with a channel. Please uncomment the following lines in main.py and run it once:
# service_id = api_handler.create_service(CHANNEL_DESCRIPTION)
# bind_result = api_handler.bind_service_with_channel(service_id, CHANNEL_ID)
# if bind_result:
# redis_instance.connection.set("service_id", service_id)To initialize the channel, set visible features and user list, please modify the initialize_data() method in ws_handler.py. If you create a singleton user with singleton_local_id 'fortune', you could append it in your initialize_data() method.
To create a singleton user, please uncomment the following lines in ws_handler.py and run it once:
# avatar = api_handler.upload_file("fortune.jpg")
# avatar = "https://social-public-bucket-1.s3.amazonaws.com/46fae16b-c72c-455f-aa51-0875d6187019.jpg"
# singleton_local_id = "fortune3"
# username = "fortune"
# nickname = "Ms Fortune"
# description = "I'm Ms Fortune"
# create_singleton_user_result = api_handler.try_create_singleton_service_user(service_id, singleton_local_id, username, nickname, avatar, description)