Mango (previously deriving from "Mastodon" and "Django") is a Federated Social Network Bot Framework for Django.
- Extensible framework for serving content to federated social platforms like Mastodon and Bluesky
- A robust API for seamless integration across diverse federated platforms
- Crossposting support to multiple accounts with custom feed configurations
- Streamlined post and account management for effortless maintenance
- Containerised in Ubuntu or minimal Alpine flavours for a reliable and secure deployment strategy
- Enables applications that serve local news from RSS feeds and real-time prayer times for multiple countries
The Mango framework is actively being used as the underlying framework for the following applications:
- Rizz: A simple web application that tracks and posts content from RSS feeds to Federated Social Networks
- WaktuSolat: A simple web application that offers real-time prayer time notifications on Federated Social Networks
Note
Mango is built on top of Dim (a custom slim image of Django), hence its list of requirements also applies.
Mango's list of requirements are as stipulated in the application's requirements.txt
file.
Mango is primarily designed to be deployed and developed upon in a containerised environment.
For the best development and deployment strategy, please use the provided container image as the base of your application:
FROM ghcr.io/irfanhakim-as/mango:latest as base
# perform any additional steps required by your application
Mango is comprised of several key modules:
- base: Base module containing most of Mango's core functionality
- models: Mango database
- conf: Mango application settings
- data: Mango model data source
- lib: Mango libraries and module extensions
- commands: Mango management commands
Important
Typically, the extending application is not expected to make any direct changes to the base
module.
Design your application around what has been implemented and established in the base
module, and extend upon it in the lib
module which can then be used in your application in its place or in addition. This way, core functionalities of Mango could be reused or enhanced upon according to your application's requirements.
Some notable components of the base module are as follows:
- base.apps: Application registry. By default, it is used to initialise Mango's signals upon application start. It is currently not possible to modify this module without replacing it entirely.
- base.messages: Core message and icon dictionaries used by Mango. Changes and enhancements can be made through its existing extension, lib.messages.
- base.methods: Core methods used by Mango. A custom module (i.e.
lib.methods
) could be implemented as an alternative or extension of this module in your application. - base.post: Core post methods used by Mango. Changes and enhancements can be made through its existing extension, lib.post.
- base.scheduler: Core module responsible for post scheduling. Changes and enhancements can be made through its existing extension, lib.scheduler.
- base.signals: Core module containing Mango's critical signals logic responsible for features such as scheduling newly created posts and updating managed accounts. It is currently not possible to modify this module without replacing it entirely.
- base.urls: Core URL routing module for Mango. This module defines the main URL patterns for the base application. It is currently not possible to modify this module without replacing it entirely.
In Django's words:
A model is the single, definitive source of information about your data. Generally, each model maps to a single database table.
By default, Mango's core models are comprised of:
- models.account: Account model (
AccountObject
) - models.feed: Feed model (
FeedObject
) - models.post: Post model (
PostItem
) - models.schedule: Schedule model (
PostSchedule
)
... Each of which are extensions of base or template models implemented in models.base.
In some cases, you may want to add, remove, or replace certain models in your application. To do so:
-
Add your new model to the
models
module (i.e.models/examplemodel.py
). The model itself can be an original model or an extension of a models.base model. -
Add your new model to the models.__init__ module:
from .examplemodel import ExampleModel
-
In your application, you can then import and use the model as follows:
from base.methods import get_model # import the newly created model ExampleModel = get_model("ExampleModel") # use the model example_model_objects = ExampleModel.objects.all()
-
It is generally not recommended to remove a core model from Mango entirely.
If you are deleting your own model or a core model with the intent of replacing it, simply remove the model from the models.__init__ module:
from .account import AccountObject from .feed import FeedObject - from .post import PostItem from .schedule import PostSchedule
This is an example of removing the default Post model (i.e.
PostItem
) to replace it with your own.
-
Create the new model by extending the appropriate base model from models.base:
- Account model:
ObjectAccount
- Feed model:
ObjectFeed
- Post model:
ObjectItem
- Schedule model:
ObjectSchedule
It is strongly recommended that you refer to any of the core models you are replacing to see how you can extend these base models.
- Account model:
-
After adding the replacement model to the models.__init__ module, remove the model that it is replacing.
For example:
- from .post import PostItem + from .custompost import CustomPostModel
-
The Mango application needs to be aware of the new model that is replacing a core model.
To do so, you will need to update the (default) value of the following setting variable, depending on the core model you are replacing:
- Account model:
ACCOUNT_MODEL
- Feed model:
FEED_MODEL
- Post model:
POST_MODEL
- Schedule model:
SCHEDULE_MODEL
For example, if you are replacing the core Post model with your own (i.e.
CustomPostModel
), update the corresponding setting's default value as follows:POST_MODEL
:base.CustomPostModel
Doing so will ensure that the application uses your new model (i.e.
CustomPostModel
) in place of the core model (i.e.PostItem
). - Account model:
Most configurable settings in a Mango application are defined in a settings file that resides in the conf
module. This way, these settings can be read and accessed from anywhere in your application in a consistent manner.
By default, Mango's core settings are defined in the conf.base module. An extension of this module exists as conf.main, which is the central location where the application settings are read from. To update a core setting or add new settings, do so through the conf.main module accordingly.
-
Add the new setting required by your application to the conf.main module:
from base.conf.base import * + + EXAMPLE_SETTING = os.getenv("EXAMPLE_SETTING_ENV", "default_value")
This example adds a new setting called
EXAMPLE_SETTING
that has the default value ofdefault_value
and can be supplied a value at runtime to its environment variable,EXAMPLE_SETTING_ENV
. -
Defining the setting this way allows the setting's value to be supplied as an environment variable to the application at runtime.
For example, to do so right in the Dockerfile packaging the application:
ENV EXAMPLE_SETTING_ENV=custom_value
In doing so, the
EXAMPLE_SETTING
setting will take on the value ofcustom_value
at runtime. -
The setting you have defined can then be read in your application as follows:
from django.conf import settings # get the setting EXAMPLE_SETTING = getattr(settings, "EXAMPLE_SETTING") # use the setting print(EXAMPLE_SETTING)
-
Identify the setting you wish to update from the conf.base module.
For example, you wish to update the default value of the setting that defines the timezone used by the scheduler (i.e.
SCHEDULER_TIMEZONE
):SCHEDULER_TIMEZONE = os.getenv("SCHEDULER_TIMEZONE", "Asia/Kuala_Lumpur")
-
Update the setting by redefining it in the conf.main module with your changes:
from base.conf.base import * + SCHEDULER_TIMEZONE = os.getenv("SCHEDULER_TIMEZONE", "UTC")
-
At runtime, the setting you have updated should now take the place of the default setting.
In Mango, it is possible to flag a setting as required or compulsory. In doing so, the application will fail to start if the setting is not defined or has not been supplied a value.
-
Update the setting
COMPULSORY_SETTINGS
in the conf.main module:COMPULSORY_SETTINGS.extend([ "EXAMPLE_SETTING", ])
Instead of redefining it from scratch, simply extend the list to include additional settings you wish to make compulsory.
-
Now, the application will fail the required tests to start if the required setting (i.e.
EXAMPLE_SETTING
) is not defined or has not been supplied a value.
The data
module is home to core data files, in JSON, used by Mango. This list includes:
- data.accounts: Account configuration data
- data.feeds: Feed configuration data
These data files are essential and offer a simple way for system administrators to configure managed social network accounts, as well as content feeds such as RSS or API endpoints, and supply them to the application at runtime.
Any additional data files needed by your application can be added to this module as well. In such cases, if you intend to use the data file as a data source and have it sync to i.e. a custom model at runtime, update the SYNC_CONFIG
setting like so:
SYNC_CONFIG["example_key"] = {
"model": EXAMPLE_MODEL,
"data": EXAMPLE_DATA_FILE,
# include the following if your model has fields that require uniqueness
# "object_id": ("example_id",),
}
Important libraries such as all the necessary integrations for Bluesky and Mastodon are defined in the lib
module:
- lib.bluesky: Bluesky library
- lib.mastodon: Mastodon library
Any additional libraries and future integrations for enhancing Mango should be placed in this module.
Extensions to Mango's core base
modules could also be found in this module, such as:
- lib.messages: Extension of base.messages
- lib.post: Extension of base.post
- lib.scheduler: Extension of base.scheduler
These extensions, and any additional extension you wish to add can be used to modify or add functionalities to the core modules safely.
Django management commands act as a way to customise or add additional commands that can be used to perform certain tasks while the application is running.
By default, Mango's commands
module contains the following commands:
- commands.check_db: Verifies the connection between the application and the database.
- commands.check_health: Checks the health of managed bots by sending a test post on each of them
- commands.clean_data: Updates and cleans post/content related data from the database
- commands.entrypoint: Entry point script for the application
- commands.post_scheduler: Runs the post scheduler to send scheduled posts
- commands.sync_data: Synchronises data from data files as per the
SYNC_CONFIG
configuration to the database - commands.update_accounts: Updates managed social network accounts based on their model objects
Should your application require any additional commands, you may refer to these commands on how to easily create your own and add them to this module accordingly.
To run a management command, do the following while the Mango application is running:
python3 manage.py <command>
Replace <command>
with the name of the command module you wish to run (i.e. example_command
).
This project is licensed under the AGPL-3.0-only license. Please refer to the LICENSE file for more information.