Observed since 20 Oct, 17:00 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Event calendar plugin app for Alliance Auth
An operation calendar app for Alliance Auth to display fleet operations and other events.
/signup <number> [attending|maybe|declined] slash command to sign up for events directly from Discord
![]() Dark theme |
![]() Light theme |
![]() Details for manual events |
![]() Event list command |
![]() Event treacker in discord channel |
py-cord>=2.0,<3.0 (only needed if you use the Discord event channel bot)pip install aa-opcalendar
'opcalendar' to your INSTALLED_APPS in your project's local.pypython manage.py migrate
python manage.py collectstatic
supervisorctl restart myauth:
Opcalendar can automatically import predetermined NPSI fleets directly into your calendar from public NPSI community APIs. This is entirely optional — skip this if you don't need it.
local.py (or set up a periodic task for
opcalendar.tasks.import_all_npsi_fleets in the admin menu) to run
imports hourly:
CELERYBEAT_SCHEDULE['import_all_npsi_fleets'] = {
'task': 'opcalendar.tasks.import_all_npsi_fleets',
'schedule': crontab(minute=0, hour='*'),
}
supervisorctl restart myauth:
See Importing NPSI fleets for the list of supported NPSI communities.
Opcalendar can pull fleets directly from in-game (ESI) personal, corporation and alliance calendars. This is entirely optional — skip this if you don't need it.
add_ingame_calendar_owner permission to the wanted groups
(see Permissions).Add Ingame Calendar Feed
button, then log in with the character that holds the calendar you want
to import.local.py (or set up a periodic task for
opcalendar.tasks.update_all_ingame_events in the admin menu) to pull
fleets from ingame every 5 minutes:
CELERYBEAT_SCHEDULE['update_all_ingame_events'] = {
'task': 'opcalendar.tasks.update_all_ingame_events',
'schedule': crontab(minute='*/5'),
}
supervisorctl restart myauth:
See Importing fleets from ingame calendar for how imported events are displayed and how to assign a visibility filter and category to them.
Opcalendar can generate a standard ical-formatted feed of events for export into personal calendar apps. This is entirely optional — skip this if you don't need it.
'opcalendar' to APPS_WITH_PUBLIC_VIEWS in your local.py
(create the setting if it doesn't exist):
APPS_WITH_PUBLIC_VIEWS = [
'opcalendar',
]
supervisorctl restart myauth:
auth.example.com/opcalendar/feed.icsOpcalendar can run a self-hosted Discord bot that posts and keeps a single
pinned summary embed of upcoming events in sync inside a Discord channel,
and lets members sign up via a /signup slash command. This is entirely
optional — skip this if you don't need it.
local.py:
OPCALENDAR_DISCORD_BOT_TOKEN = "your-bot-token-here"
/etc/supervisor/conf.d/myauth.conf), adjusting the paths to match your
install:
[program:opcalendar_event_channel_bot]
command=/home/allianceserver/venv/auth/bin/python /home/allianceserver/myauth/manage.py run_event_channel_bot
directory=/home/allianceserver/myauth
user=allianceserver
numprocs=1
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
stderr_logfile=/home/allianceserver/myauth/log/opcalendar_event_channel_bot.err.log
stdout_logfile=/home/allianceserver/myauth/log/opcalendar_event_channel_bot.out.log
The Discord ping timing feature (1 hour/1 day/1 week before fleet, or a custom date and time) requires a periodic task to actually send those reminders. The "Now" ping does not need this, since it's sent immediately when the event is created.
Add the following to your local.py (or set up a periodic task for opcalendar.tasks.send_scheduled_event_notifications in the admin menu) so due reminders are checked and sent every 5 minutes:
CELERYBEAT_SCHEDULE['send_scheduled_event_notifications'] = {
'task': 'opcalendar.tasks.send_scheduled_event_notifications',
'schedule': crontab(minute='*/5'),
}
[!IMPORTANT] Without this task scheduled, only the "Now" ping will be sent — the 1 hour/1 day/1 week and custom-time reminders will silently never fire.
supervisorctl reread
supervisorctl update
supervisorctl restart opcalendar_event_channel_bot
conf/requirements.txt:
aa-opcalendar==<latest stable version>
'opcalendar' to INSTALLED_APPS in your conf/local.pydocker compose build --no-cache
docker compose up -d
docker compose exec allianceauth_gunicorn bash
auth migrate
auth collectstatic
Opcalendar can automatically import predetermined NPSI fleets directly into your calendar from public NPSI community APIs. This is entirely optional — skip this if you don't need it.
conf/local.py (or set up a periodic task for
opcalendar.tasks.import_all_npsi_fleets in the admin menu) to run
imports hourly:
CELERYBEAT_SCHEDULE['import_all_npsi_fleets'] = {
'task': 'opcalendar.tasks.import_all_npsi_fleets',
'schedule': crontab(minute=0, hour='*'),
}
docker compose restart allianceauth_gunicorn allianceauth_worker allianceauth_beat
See Importing NPSI fleets for the list of supported NPSI communities.
Opcalendar can pull fleets directly from in-game (ESI) personal, corporation and alliance calendars. This is entirely optional — skip this if you don't need it.
add_ingame_calendar_owner permission to the wanted groups
(see Permissions).Add Ingame Calendar Feed
button, then log in with the character that holds the calendar you want
to import.conf/local.py (or set up a periodic task for
opcalendar.tasks.update_all_ingame_events in the admin menu) to pull
fleets from ingame every 5 minutes:
CELERYBEAT_SCHEDULE['update_all_ingame_events'] = {
'task': 'opcalendar.tasks.update_all_ingame_events',
'schedule': crontab(minute='*/5'),
}
docker compose restart allianceauth_gunicorn allianceauth_worker allianceauth_beat
See Importing fleets from ingame calendar for how imported events are displayed and how to assign a visibility filter and category to them.
Opcalendar can generate a standard ical-formatted feed of events for export into personal calendar apps. This is entirely optional — skip this if you don't need it.
'opcalendar' to APPS_WITH_PUBLIC_VIEWS in your conf/local.py
(create the setting if it doesn't exist):
APPS_WITH_PUBLIC_VIEWS = [
'opcalendar',
]
docker compose restart allianceauth_gunicorn allianceauth_worker allianceauth_beat
auth.example.com/opcalendar/feed.icsOpcalendar can run a self-hosted Discord bot that posts and keeps a single
pinned summary embed of upcoming events in sync inside a Discord channel,
and lets members sign up via a /signup slash command. This is entirely
optional — skip this if you don't need it.
conf/local.py:
OPCALENDAR_DISCORD_BOT_TOKEN=your-bot-token-here
docker-compose.yml, reusing the
x-allianceauth-base anchor shared by
allianceauth_gunicorn/allianceauth_beat/allianceauth_worker so it
inherits the same image, env_file, volumes, depends_on, working
directory and logging:
allianceauth_opcalendar_bot:
container_name: allianceauth_opcalendar_bot
<<: [*allianceauth-base]
entrypoint: ["python3", "manage.py", "run_event_channel_bot"]
The Discord ping timing feature (1 hour/1 day/1 week before fleet, or a custom date and time) requires a periodic task to actually send those reminders. The "Now" ping does not need this, since it's sent immediately when the event is created.
Add the following to your local.py (or set up a periodic task for opcalendar.tasks.send_scheduled_event_notifications in the admin menu) so due reminders are checked and sent every 5 minutes:
CELERYBEAT_SCHEDULE['send_scheduled_event_notifications'] = {
'task': 'opcalendar.tasks.send_scheduled_event_notifications',
'schedule': crontab(minute='*/5'),
}
[!IMPORTANT] Without this task scheduled, only the "Now" ping will be sent — the 1 hour/1 day/1 week and custom-time reminders will silently never fire.
docker compose up -d allianceauth_opcalendar_bot
docker compose logs -f allianceauth_opcalendar_bot
[!NOTE] If
OPCALENDAR_DISCORD_BOT_TOKENis unset/blank, this container will start and immediately exit — the bot management command no-ops when the feature is disabled. Set the token first, or don't add this service until you're ready to use the Discord sign-up feature.
| Perm | Auth Site | Example Target Group |
|---|---|---|
| opcalendar basic_access | Can access this app and see operations based on visibility rules | Everyone |
| opcalendar create_event | Can create new events and edit/delete their own events | Members, FCs |
| opcalendar manage_event | Can edit and delete their own events | Members, FCs |
| opcalendar manage_all_events | Can edit and delete all events, including events created by other users | Leadership, FCs |
| opcalendar see_signups | Can see all signups for event | Leadership, FCs, Members |
| opcalendar add_ingame_calendar_owner | Can add ingame calendar feeds for their corporation | Leadership, FCs |
| Name | Description | Default |
|---|---|---|
| OPCALENDAR_NOTIFY_IMPORTS | Whether to send out discord notifications for ingame and public NPSI events | True |
| OPCALENDAR_DISPLAY_STRUCTURETIMERS | Whether we should include timers from the structuretimers plugin in the calendar. Inherits view permissions from aa-structuretimers | True |
| OPCALENDAR_DISPLAY_MOONMINING | Whether we should include extractions from the aa-moonmining plugin in the calendar. Inherits view permissions from aa-moonmining | True |
| OPCALENDAR_DISCORD_OPS_DISPLAY_EXTERNAL | Whether we display external hosts such as ingame hosts in the discord ops command filters | False |
| OPCALENDAR_DISPLAY_MOONMINING_TAGS | Display the rarity tag of aa-moonmining moons if the moonmining plugin is installed | True |
| OPCALENDAR_DISPLAY_MOONMINING_ARRIVAL_TIME | Displays aa-moonmining extraction time based on arrival time. Set to False to display as auto fracture time | True |
| OPCALENDAR_NOTIFY_REPEAT_EVENTS | If repeated events should also be created as webhook pings on discord. Can create spam if the event repeat is set to high | True |
| OPCALENDAR_SHOW_EVENT_COUNTER | Shows a counter next to the opcalendar menu for events that the user has not responded to | True |
| OPCALENDAR_TASKS_TIME_LIMIT | Hard timeout for opcalendar's periodic tasks in seconds, to reduce task accumulation during outages | 7200 |
| OPCALENDAR_DISCORD_BOT_TOKEN | Bot token for the self-hosted Discord event channel bot. Leave blank to disable the feature entirely | "" (empty) |
Before you are able to create new events on the front end you will need to set up the needed hosts, categories and visibility filters for your events. All of the following are configured from the Django admin site.
Hosts are for identifying reasons. If you run a single corporation or alliance entity you most likely only want one host. If you want to extend the calendar with other hosts such as NPSI communities you can create a host for each different entity.
These filters will determine who is able to see the events that are labeled with each different visibility filter.
Categories are displayed as a ticker in front of manually created events. Most common categories are: PvP, Stratop, Mining, CTA etc.
fas fa-rocket), tinted with the category's color, shown in the calendar's left gutter. If no icon is set but a color is, a small colored dot is shown instead. Both blink for events marked "Important".If you want to receive notifications about your events (created/modified/deleted) on your discord you can add a webhook for the channel in discord you want to receive the notifications to. The webhooks you create will be used in the visibility filters.
To add a manual event simply go to the calendar page and press on the new event button. Fill in and select the needed information.
You can mark an event as Important to show a blinking red indicator on the calendar (and on its category icon/dot, if any) so members notice it at a glance. Ingame (ESI) calendar events that EVE itself flags as important get this automatically.
When creating or editing an event you can choose when the Discord ping for it should be sent out. This is a multi select field, so you can pick multiple timings for the same event:
The "Now" ping is sent out instantly when the event is created. All other timings ("1 hour/day/week before fleet" and "Custom date and time") are picked up by a periodic task that checks for due notifications and sends them out.
On the event details page, the owner of an event (the user who created it) will see a Send starting now ping button. This lets you instantly notify your Discord channel that the fleet is starting, regardless of which scheduled ping timings were selected when the event was created. Next to the button you can choose who the ping should mention:
The notification is sent through the same webhook configured on the event's visibility filter, so it respects that filter's enabled/ignore-past-fleets settings.
Opcalendar has the ability to import predetermined NPSI fleets directly into your calendar from public NPSI community APIs.
This feature is optional and set up as part of the installation steps (see "Optional: Importing NPSI fleets" under either the Standard or Docker installation method).
[!NOTE] Don't forget to also set up the
send_scheduled_event_notificationsperiodic task described in Setup — Periodic task for scheduled Discord pings — it's required for the Discord ping timing feature and is unrelated to NPSI imports.
Opcalendar is currently supporting imports for the following NPSI fleets:
You can import events that have been created in the ingame calendar. As the fields on the ingame calendar are limited the events will not be as detailed as when created directly from the calendar.
This feature is optional and set up as part of the installation steps (see "Optional: Importing fleets from ingame calendar" under either the Standard or Docker installation method).
By default, the ingame events you import have no visibility filter and no category. This means they will be visible for everyone.
If you wish to add a visibility filter or a category similar to the manual events, go to admin panel → Ingame event owners and select a filter and a category for the owner.
After selecting a visibility filter and a category, the ingame events will behave similarly to manual events and respect the group and state restrictions set for the visibility filters. Ingame events EVE itself flags as important will also show the "Important" blinking indicator automatically.
Opcalendar can run a self-hosted Discord bot that posts and keeps a single pinned summary embed of upcoming events (both manually created events and ingame ESI events) in sync inside a Discord channel, and lets members sign up for events directly from Discord using a slash command.
This feature is optional and set up as part of the installation steps (see "Optional: Discord event channel bot" under either the Standard or Docker installation method).
Members can sign up for an event listed in the pinned summary using the /signup <number> [attending|maybe|declined] slash command from within the event channel, where <number> is the position of the event as listed in the pinned summary.
Make sure you have signed the License Agreement by logging in at https://developers.eveonline.com before submitting any pull requests. All bug fixes or features must not include extra superfluous formatting changes.
pypistats · 88 observations shown. Missing days are unknown. Source category: overall: without mirrors.
| Date / source period | Value | Observed at |
|---|---|---|
| 2026-10-19 – 2026-10-19 | 7 | 2026-10-20T19:53:33.4697662Z |
| 2026-10-18 – 2026-10-18 | 4 | 2026-10-20T19:53:33.4697662Z |
| 2026-10-17 – 2026-10-17 | 6 | 2026-10-20T19:53:33.4697662Z |
| 2026-10-16 – 2026-10-16 | 6 | 2026-10-20T19:53:33.4697662Z |
| 2026-10-15 – 2026-10-15 | 3 | 2026-10-20T19:53:33.4697662Z |
| 2026-10-13 – 2026-10-13 | 5 | 2026-10-20T19:53:33.4697662Z |
| 2026-10-12 – 2026-10-12 | 3 | 2026-10-20T19:53:33.4697662Z |
| 2026-10-11 – 2026-10-11 | 6 | 2026-10-20T19:53:33.4697662Z |
| 2026-10-10 – 2026-10-10 | 30 | 2026-10-20T19:53:33.4697662Z |
| 2026-10-09 – 2026-10-09 | 36 | 2026-10-20T19:53:33.4697662Z |
| 2026-10-08 – 2026-10-08 | 11 | 2026-10-20T19:53:33.4697662Z |
| 2026-10-07 – 2026-10-07 | 9 | 2026-10-20T19:53:33.4697662Z |
| 2026-10-06 – 2026-10-06 | 7 | 2026-10-20T19:53:33.4697662Z |
| 2026-10-05 – 2026-10-05 | 8 | 2026-10-20T19:53:33.4697662Z |
| 2026-10-04 – 2026-10-04 | 3 | 2026-10-20T19:53:33.4697662Z |
| 2026-10-03 – 2026-10-03 | 7 | 2026-10-20T19:53:33.4697662Z |
| 2026-10-02 – 2026-10-02 | 10 | 2026-10-20T19:53:33.4697662Z |
| 2026-10-01 – 2026-10-01 | 14 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-30 – 2026-09-30 | 73 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-29 – 2026-09-29 | 31 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-28 – 2026-09-28 | 33 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-27 – 2026-09-27 | 98 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-26 – 2026-09-26 | 35 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-25 – 2026-09-25 | 38 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-24 – 2026-09-24 | 21 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-23 – 2026-09-23 | 24 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-22 – 2026-09-22 | 22 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-21 – 2026-09-21 | 4 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-20 – 2026-09-20 | 3 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-19 – 2026-09-19 | 28 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-18 – 2026-09-18 | 19 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-17 – 2026-09-17 | 16 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-16 – 2026-09-16 | 14 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-15 – 2026-09-15 | 5 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-14 – 2026-09-14 | 11 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-13 – 2026-09-13 | 24 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-12 – 2026-09-12 | 23 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-11 – 2026-09-11 | 5 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-10 – 2026-09-10 | 2 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-09 – 2026-09-09 | 19 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-08 – 2026-09-08 | 13 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-07 – 2026-09-07 | 50 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-06 – 2026-09-06 | 41 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-05 – 2026-09-05 | 52 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-04 – 2026-09-04 | 10 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-03 – 2026-09-03 | 18 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-02 – 2026-09-02 | 4 | 2026-10-20T19:53:33.4697662Z |
| 2026-09-01 – 2026-09-01 | 29 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-31 – 2026-08-31 | 48 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-30 – 2026-08-30 | 105 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-29 – 2026-08-29 | 5 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-28 – 2026-08-28 | 97 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-27 – 2026-08-27 | 4 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-26 – 2026-08-26 | 7 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-25 – 2026-08-25 | 5 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-24 – 2026-08-24 | 116 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-23 – 2026-08-23 | 14 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-22 – 2026-08-22 | 13 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-21 – 2026-08-21 | 9 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-20 – 2026-08-20 | 14 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-19 – 2026-08-19 | 13 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-18 – 2026-08-18 | 68 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-17 – 2026-08-17 | 26 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-16 – 2026-08-16 | 32 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-15 – 2026-08-15 | 24 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-14 – 2026-08-14 | 19 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-13 – 2026-08-13 | 38 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-12 – 2026-08-12 | 46 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-11 – 2026-08-11 | 89 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-10 – 2026-08-10 | 73 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-09 – 2026-08-09 | 25 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-07 – 2026-08-07 | 18 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-06 – 2026-08-06 | 16 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-05 – 2026-08-05 | 31 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-04 – 2026-08-04 | 12 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-03 – 2026-08-03 | 22 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-02 – 2026-08-02 | 49 | 2026-10-20T19:53:33.4697662Z |
| 2026-08-01 – 2026-08-01 | 22 | 2026-10-20T19:53:33.4697662Z |
| 2026-07-31 – 2026-07-31 | 20 | 2026-10-20T19:53:33.4697662Z |
| 2026-07-30 – 2026-07-30 | 4 | 2026-10-20T19:53:33.4697662Z |
| 2026-07-29 – 2026-07-29 | 19 | 2026-10-20T19:53:33.4697662Z |
| 2026-07-28 – 2026-07-28 | 33 | 2026-10-20T19:53:33.4697662Z |
| 2026-07-27 – 2026-07-27 | 6 | 2026-10-20T19:53:33.4697662Z |
| 2026-07-26 – 2026-07-26 | 2 | 2026-10-20T19:53:33.4697662Z |
| 2026-07-25 – 2026-07-25 | 28 | 2026-10-20T19:53:33.4697662Z |
| 2026-07-24 – 2026-07-24 | 10 | 2026-10-20T19:53:33.4697662Z |
| 2026-07-23 – 2026-07-23 | 14 | 2026-10-20T19:53:33.4697662Z |
| 2026-07-22 – 2026-07-22 | 15 | 2026-10-20T19:53:33.4697662Z |
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 4.0.1 | 30 Aug 2026 | 8 |
This describes our collected data; it is not a security assessment.
Shared repository data · GitLab
| Contributor | Contributions |
|---|---|
| Ikarus Cesaille | 141 |
| root | 63 |
| Ikarus Cesaille | 24 |
| ErikKalkoken | 22 |
| Peter Pfeufer | 7 |
Default-branch author identities; GitLab commit counts exclude merge commits.
Public sponsor counts have not been collected. These signals belong to the repository owner.
gitlab · 5 observations shown. Missing days are unknown.
| Date / source period | Value | Observed at |
|---|---|---|
| 2026-10-24 | 5 | 2026-10-24T17:48:52.5715192Z |
| 2026-10-23 | 5 | 2026-10-23T17:46:35.4379414Z |
| 2026-10-22 | 5 | 2026-10-22T17:45:17.7032882Z |
| 2026-10-21 | 5 | 2026-10-21T17:44:49.2580989Z |
| 2026-10-20 | 5 | 2026-10-20T17:44:30.1266410Z |
Observed since 20 Oct, 17:00 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:22564e8afee415de2b273d073a43ce3b240dbde3cc4c7954d7515945f6e87cc5