indy-hub 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- indy_hub-0.1.1/LICENSE +21 -0
- indy_hub-0.1.1/PKG-INFO +122 -0
- indy_hub-0.1.1/README.md +88 -0
- indy_hub-0.1.1/indy_hub/__init__.py +5 -0
- indy_hub-0.1.1/indy_hub/admin.py +173 -0
- indy_hub-0.1.1/indy_hub/apps.py +94 -0
- indy_hub-0.1.1/indy_hub/auth_hooks.py +69 -0
- indy_hub-0.1.1/indy_hub/decorators.py +79 -0
- indy_hub-0.1.1/indy_hub/esi_helpers.py +141 -0
- indy_hub-0.1.1/indy_hub/management/__init__.py +0 -0
- indy_hub-0.1.1/indy_hub/management/commands/__init__.py +0 -0
- indy_hub-0.1.1/indy_hub/management/commands/cache_esi_data.py +145 -0
- indy_hub-0.1.1/indy_hub/management/commands/esi_status.py +82 -0
- indy_hub-0.1.1/indy_hub/migrations/0001_initial.py +170 -0
- indy_hub-0.1.1/indy_hub/migrations/0002_blueprint_character_name_industryjob_character_name.py +24 -0
- indy_hub-0.1.1/indy_hub/migrations/0003_characterupdatetracker_last_refresh_request.py +19 -0
- indy_hub-0.1.1/indy_hub/migrations/0004_alter_characterupdatetracker_options_and_more.py +28 -0
- indy_hub-0.1.1/indy_hub/migrations/0006_blueprint_copy_share_and_request.py +80 -0
- indy_hub-0.1.1/indy_hub/migrations/0007_alter_blueprintcopyrequest_id_and_more.py +28 -0
- indy_hub-0.1.1/indy_hub/migrations/0008_add_copies_requested.py +17 -0
- indy_hub-0.1.1/indy_hub/migrations/0009_blueprintcopyoffer.py +60 -0
- indy_hub-0.1.1/indy_hub/migrations/0010_add_delivered_to_copyrequest.py +22 -0
- indy_hub-0.1.1/indy_hub/migrations/0011_alter_blueprintcopyoffer_id.py +21 -0
- indy_hub-0.1.1/indy_hub/migrations/0012_industryjob_job_completed_notified.py +19 -0
- indy_hub-0.1.1/indy_hub/migrations/0013_characterupdatetracker_jobs_notify_completed.py +19 -0
- indy_hub-0.1.1/indy_hub/migrations/0014_alter_blueprint_options_and_more.py +43 -0
- indy_hub-0.1.1/indy_hub/migrations/__init__.py +0 -0
- indy_hub-0.1.1/indy_hub/models.py +385 -0
- indy_hub-0.1.1/indy_hub/notifications.py +44 -0
- indy_hub-0.1.1/indy_hub/schedules.py +37 -0
- indy_hub-0.1.1/indy_hub/signals.py +115 -0
- indy_hub-0.1.1/indy_hub/static/indy_hub/css/blueprints.css +304 -0
- indy_hub-0.1.1/indy_hub/static/indy_hub/css/craft_bp.css +70 -0
- indy_hub-0.1.1/indy_hub/static/indy_hub/css/index.css +47 -0
- indy_hub-0.1.1/indy_hub/static/indy_hub/css/jobs.css +560 -0
- indy_hub-0.1.1/indy_hub/static/indy_hub/css/page_headers.css +48 -0
- indy_hub-0.1.1/indy_hub/static/indy_hub/css/token_management.css +66 -0
- indy_hub-0.1.1/indy_hub/static/indy_hub/js/blueprints.js +413 -0
- indy_hub-0.1.1/indy_hub/static/indy_hub/js/craft_bp.js +290 -0
- indy_hub-0.1.1/indy_hub/static/indy_hub/js/index.js +61 -0
- indy_hub-0.1.1/indy_hub/static/indy_hub/js/jobs.js +392 -0
- indy_hub-0.1.1/indy_hub/static/indy_hub/js/personal_bp_list.js +25 -0
- indy_hub-0.1.1/indy_hub/static/indy_hub/js/personal_job_list.js +44 -0
- indy_hub-0.1.1/indy_hub/static/indy_hub/js/token_management.js +28 -0
- indy_hub-0.1.1/indy_hub/tasks/__init__.py +43 -0
- indy_hub-0.1.1/indy_hub/tasks/industry.py +432 -0
- indy_hub-0.1.1/indy_hub/tasks/user.py +161 -0
- indy_hub-0.1.1/indy_hub/tasks.py +37 -0
- indy_hub-0.1.1/indy_hub/tasks_new.py +0 -0
- indy_hub-0.1.1/indy_hub/templates/indy_hub/All_BP_list.html +152 -0
- indy_hub-0.1.1/indy_hub/templates/indy_hub/Craft_BP.html +242 -0
- indy_hub-0.1.1/indy_hub/templates/indy_hub/Personnal_BP_list.html +324 -0
- indy_hub-0.1.1/indy_hub/templates/indy_hub/Personnal_Job_list.html +187 -0
- indy_hub-0.1.1/indy_hub/templates/indy_hub/blueprint_list.html +0 -0
- indy_hub-0.1.1/indy_hub/templates/indy_hub/bp_copy_fulfill_requests.html +100 -0
- indy_hub-0.1.1/indy_hub/templates/indy_hub/bp_copy_my_requests.html +90 -0
- indy_hub-0.1.1/indy_hub/templates/indy_hub/bp_copy_request_page.html +142 -0
- indy_hub-0.1.1/indy_hub/templates/indy_hub/index.html +291 -0
- indy_hub-0.1.1/indy_hub/templates/indy_hub/material_tree.html +31 -0
- indy_hub-0.1.1/indy_hub/templates/indy_hub/token_management.html +218 -0
- indy_hub-0.1.1/indy_hub/templatetags/__init__.py +0 -0
- indy_hub-0.1.1/indy_hub/templatetags/dict_get.py +12 -0
- indy_hub-0.1.1/indy_hub/urls.py +95 -0
- indy_hub-0.1.1/indy_hub/utils/__init__.py +3 -0
- indy_hub-0.1.1/indy_hub/utils/industry.py +89 -0
- indy_hub-0.1.1/indy_hub/utils/user.py +84 -0
- indy_hub-0.1.1/indy_hub/utils.py +0 -0
- indy_hub-0.1.1/indy_hub/views/__init__.py +3 -0
- indy_hub-0.1.1/indy_hub/views/api.py +119 -0
- indy_hub-0.1.1/indy_hub/views/industry.py +1070 -0
- indy_hub-0.1.1/indy_hub/views/user.py +441 -0
- indy_hub-0.1.1/indy_hub/views.py +0 -0
- indy_hub-0.1.1/pyproject.toml +65 -0
indy_hub-0.1.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 erka Ekanon
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
indy_hub-0.1.1/PKG-INFO
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: indy-hub
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Indy Hub Plugin for Alliance Auth
|
|
5
|
+
Keywords: allianceauth,eveonline,hub,industry,indy
|
|
6
|
+
Author-email: erka Ekanon <erkaekanon@outlook.com>
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Classifier: Environment :: Web Environment
|
|
10
|
+
Classifier: Framework :: Celery
|
|
11
|
+
Classifier: Framework :: Django
|
|
12
|
+
Classifier: Framework :: Django :: 4.0
|
|
13
|
+
Classifier: Framework :: Django :: 4.2
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python
|
|
18
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
24
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
25
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: aa-discordnotify>=2
|
|
28
|
+
Requires-Dist: allianceauth>=4,<5
|
|
29
|
+
Requires-Dist: django-eveuniverse>=1.5.7
|
|
30
|
+
Project-URL: Home, https://github.com/Erkaek/aa-Indy_Hub
|
|
31
|
+
Project-URL: Source, https://github.com/Erkaek/aa-Indy_Hub
|
|
32
|
+
Project-URL: Tracker, https://github.com/Erkaek/aa-Indy_Hub/issues
|
|
33
|
+
|
|
34
|
+
# Indy Hub for Alliance Auth
|
|
35
|
+
|
|
36
|
+
A modern industry management module for [Alliance Auth](https://allianceauth.org/), focused on blueprint and job tracking for EVE Online alliances and corporations.
|
|
37
|
+
|
|
38
|
+
______________________________________________________________________
|
|
39
|
+
|
|
40
|
+
## ✨ Features (Current)
|
|
41
|
+
|
|
42
|
+
- **Blueprint Library**: View, filter, and search all your EVE Online blueprints by character, type, and efficiency.
|
|
43
|
+
- **Industry Job Tracking**: Monitor and filter your manufacturing, research, and invention jobs in real time.
|
|
44
|
+
- **Blueprint Copy Sharing**: Request, offer, and deliver blueprint copies (BPCs) within your alliance, with notifications for each step.
|
|
45
|
+
- **ESI Integration**: Secure OAuth2-based sync for blueprints and jobs, with periodic background updates (Celery required).
|
|
46
|
+
- **Notifications**: In-app alerts for job completions, copy offers, and deliveries. Optional Discord notifications (via aa-discordnotify).
|
|
47
|
+
- **Modern UI**: Responsive Bootstrap 5 interface, theme-compatible, with accessibility and i18n support.
|
|
48
|
+
|
|
49
|
+
______________________________________________________________________
|
|
50
|
+
|
|
51
|
+
## 🚧 In Development
|
|
52
|
+
|
|
53
|
+
- **Alliance-wide Blueprint Library**: Browse all blueprints available in the alliance (admin-controlled visibility).
|
|
54
|
+
- **Advanced Copy Request Fulfillment**: Streamlined workflows for fulfilling and tracking copy requests.
|
|
55
|
+
- **Improved Job Analytics**: More detailed job statistics, filtering, and export options.
|
|
56
|
+
- **Better Admin Tools**: Enhanced dashboards and management commands for admins.
|
|
57
|
+
|
|
58
|
+
______________________________________________________________________
|
|
59
|
+
|
|
60
|
+
## 🛣️ Planned / Coming Soon
|
|
61
|
+
|
|
62
|
+
- **Blueprint Lending/Loan System**: Track and manage temporary blueprint loans between members.
|
|
63
|
+
- **Production Cost Estimation**: Integrated cost calculators and market price lookups.
|
|
64
|
+
- **More ESI Scopes**: Support for additional ESI endpoints (e.g., assets, wallet, reactions).
|
|
65
|
+
- **API/Export**: Public API endpoints and improved CSV/Excel export for all lists.
|
|
66
|
+
- **More Notifications**: Customizable notification rules and Discord webhooks.
|
|
67
|
+
|
|
68
|
+
______________________________________________________________________
|
|
69
|
+
|
|
70
|
+
## Requirements
|
|
71
|
+
|
|
72
|
+
- Alliance Auth v4+
|
|
73
|
+
- Python 3.10+
|
|
74
|
+
- Django (as required by AA)
|
|
75
|
+
- django-eveuniverse (populated with industry data)
|
|
76
|
+
- Celery (for background sync)
|
|
77
|
+
- (Optional) aa-discordnotify for Discord alerts
|
|
78
|
+
|
|
79
|
+
______________________________________________________________________
|
|
80
|
+
|
|
81
|
+
## Quick Install
|
|
82
|
+
|
|
83
|
+
1. `pip install django-eveuniverse` and `pip install indy_hub`
|
|
84
|
+
|
|
85
|
+
1. Add `eveuniverse` and `indy_hub` to `INSTALLED_APPS` in your AA settings.
|
|
86
|
+
|
|
87
|
+
1. Add to your local.py:
|
|
88
|
+
|
|
89
|
+
- EVEUNIVERSE_LOAD_TYPE_MATERIALS = True
|
|
90
|
+
- EVEUNIVERSE_LOAD_MARKET_GROUPS = True
|
|
91
|
+
- EVEUNIVERSE_LOAD_TYPE_MATERIALS = True
|
|
92
|
+
|
|
93
|
+
1. Run migrations: `python manage.py migrate`
|
|
94
|
+
|
|
95
|
+
1. Collect static files: `python manage.py collectstatic`
|
|
96
|
+
|
|
97
|
+
1. Restart your auth.
|
|
98
|
+
|
|
99
|
+
1. Populate EveUniverse with industry data `python manage.py eveuniverse_load_data types --types-enabled-sections industry_activities type_materials`.
|
|
100
|
+
|
|
101
|
+
1. Assign the `can access indy_hub` permission to users/groups.
|
|
102
|
+
|
|
103
|
+
______________________________________________________________________
|
|
104
|
+
|
|
105
|
+
## Usage
|
|
106
|
+
|
|
107
|
+
- Go to the Indy Hub dashboard in Alliance Auth.
|
|
108
|
+
- Authorize ESI for blueprints and jobs.
|
|
109
|
+
- View/manage your blueprints and jobs, request/offer BPCs, and receive notifications.
|
|
110
|
+
|
|
111
|
+
______________________________________________________________________
|
|
112
|
+
|
|
113
|
+
## Support & Contributing
|
|
114
|
+
|
|
115
|
+
- Open an issue or pull request on GitHub for help or to contribute.
|
|
116
|
+
|
|
117
|
+
______________________________________________________________________
|
|
118
|
+
|
|
119
|
+
## License
|
|
120
|
+
|
|
121
|
+
MIT License. See [LICENSE](LICENSE) for details.
|
|
122
|
+
|
indy_hub-0.1.1/README.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Indy Hub for Alliance Auth
|
|
2
|
+
|
|
3
|
+
A modern industry management module for [Alliance Auth](https://allianceauth.org/), focused on blueprint and job tracking for EVE Online alliances and corporations.
|
|
4
|
+
|
|
5
|
+
______________________________________________________________________
|
|
6
|
+
|
|
7
|
+
## ✨ Features (Current)
|
|
8
|
+
|
|
9
|
+
- **Blueprint Library**: View, filter, and search all your EVE Online blueprints by character, type, and efficiency.
|
|
10
|
+
- **Industry Job Tracking**: Monitor and filter your manufacturing, research, and invention jobs in real time.
|
|
11
|
+
- **Blueprint Copy Sharing**: Request, offer, and deliver blueprint copies (BPCs) within your alliance, with notifications for each step.
|
|
12
|
+
- **ESI Integration**: Secure OAuth2-based sync for blueprints and jobs, with periodic background updates (Celery required).
|
|
13
|
+
- **Notifications**: In-app alerts for job completions, copy offers, and deliveries. Optional Discord notifications (via aa-discordnotify).
|
|
14
|
+
- **Modern UI**: Responsive Bootstrap 5 interface, theme-compatible, with accessibility and i18n support.
|
|
15
|
+
|
|
16
|
+
______________________________________________________________________
|
|
17
|
+
|
|
18
|
+
## 🚧 In Development
|
|
19
|
+
|
|
20
|
+
- **Alliance-wide Blueprint Library**: Browse all blueprints available in the alliance (admin-controlled visibility).
|
|
21
|
+
- **Advanced Copy Request Fulfillment**: Streamlined workflows for fulfilling and tracking copy requests.
|
|
22
|
+
- **Improved Job Analytics**: More detailed job statistics, filtering, and export options.
|
|
23
|
+
- **Better Admin Tools**: Enhanced dashboards and management commands for admins.
|
|
24
|
+
|
|
25
|
+
______________________________________________________________________
|
|
26
|
+
|
|
27
|
+
## 🛣️ Planned / Coming Soon
|
|
28
|
+
|
|
29
|
+
- **Blueprint Lending/Loan System**: Track and manage temporary blueprint loans between members.
|
|
30
|
+
- **Production Cost Estimation**: Integrated cost calculators and market price lookups.
|
|
31
|
+
- **More ESI Scopes**: Support for additional ESI endpoints (e.g., assets, wallet, reactions).
|
|
32
|
+
- **API/Export**: Public API endpoints and improved CSV/Excel export for all lists.
|
|
33
|
+
- **More Notifications**: Customizable notification rules and Discord webhooks.
|
|
34
|
+
|
|
35
|
+
______________________________________________________________________
|
|
36
|
+
|
|
37
|
+
## Requirements
|
|
38
|
+
|
|
39
|
+
- Alliance Auth v4+
|
|
40
|
+
- Python 3.10+
|
|
41
|
+
- Django (as required by AA)
|
|
42
|
+
- django-eveuniverse (populated with industry data)
|
|
43
|
+
- Celery (for background sync)
|
|
44
|
+
- (Optional) aa-discordnotify for Discord alerts
|
|
45
|
+
|
|
46
|
+
______________________________________________________________________
|
|
47
|
+
|
|
48
|
+
## Quick Install
|
|
49
|
+
|
|
50
|
+
1. `pip install django-eveuniverse` and `pip install indy_hub`
|
|
51
|
+
|
|
52
|
+
1. Add `eveuniverse` and `indy_hub` to `INSTALLED_APPS` in your AA settings.
|
|
53
|
+
|
|
54
|
+
1. Add to your local.py:
|
|
55
|
+
|
|
56
|
+
- EVEUNIVERSE_LOAD_TYPE_MATERIALS = True
|
|
57
|
+
- EVEUNIVERSE_LOAD_MARKET_GROUPS = True
|
|
58
|
+
- EVEUNIVERSE_LOAD_TYPE_MATERIALS = True
|
|
59
|
+
|
|
60
|
+
1. Run migrations: `python manage.py migrate`
|
|
61
|
+
|
|
62
|
+
1. Collect static files: `python manage.py collectstatic`
|
|
63
|
+
|
|
64
|
+
1. Restart your auth.
|
|
65
|
+
|
|
66
|
+
1. Populate EveUniverse with industry data `python manage.py eveuniverse_load_data types --types-enabled-sections industry_activities type_materials`.
|
|
67
|
+
|
|
68
|
+
1. Assign the `can access indy_hub` permission to users/groups.
|
|
69
|
+
|
|
70
|
+
______________________________________________________________________
|
|
71
|
+
|
|
72
|
+
## Usage
|
|
73
|
+
|
|
74
|
+
- Go to the Indy Hub dashboard in Alliance Auth.
|
|
75
|
+
- Authorize ESI for blueprints and jobs.
|
|
76
|
+
- View/manage your blueprints and jobs, request/offer BPCs, and receive notifications.
|
|
77
|
+
|
|
78
|
+
______________________________________________________________________
|
|
79
|
+
|
|
80
|
+
## Support & Contributing
|
|
81
|
+
|
|
82
|
+
- Open an issue or pull request on GitHub for help or to contribute.
|
|
83
|
+
|
|
84
|
+
______________________________________________________________________
|
|
85
|
+
|
|
86
|
+
## License
|
|
87
|
+
|
|
88
|
+
MIT License. See [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Django admin configuration for indy_hub models
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
# Django
|
|
6
|
+
from django.contrib import admin
|
|
7
|
+
|
|
8
|
+
from .models import Blueprint, CharacterUpdateTracker, IndustryJob
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@admin.register(Blueprint)
|
|
12
|
+
class BlueprintAdmin(admin.ModelAdmin):
|
|
13
|
+
list_display = [
|
|
14
|
+
"type_name",
|
|
15
|
+
"owner_user",
|
|
16
|
+
"character_id",
|
|
17
|
+
"quantity",
|
|
18
|
+
"material_efficiency",
|
|
19
|
+
"time_efficiency",
|
|
20
|
+
"runs",
|
|
21
|
+
"last_updated",
|
|
22
|
+
]
|
|
23
|
+
list_filter = ["owner_user", "character_id", "quantity", "last_updated"]
|
|
24
|
+
search_fields = ["type_name", "type_id", "owner_user__username"]
|
|
25
|
+
readonly_fields = ["item_id", "last_updated", "created_at"]
|
|
26
|
+
|
|
27
|
+
fieldsets = (
|
|
28
|
+
(
|
|
29
|
+
"Basic Information",
|
|
30
|
+
{
|
|
31
|
+
"fields": (
|
|
32
|
+
"owner_user",
|
|
33
|
+
"character_id",
|
|
34
|
+
"item_id",
|
|
35
|
+
"type_id",
|
|
36
|
+
"type_name",
|
|
37
|
+
)
|
|
38
|
+
},
|
|
39
|
+
),
|
|
40
|
+
("Location", {"fields": ("location_id", "location_flag")}),
|
|
41
|
+
(
|
|
42
|
+
"Blueprint Details",
|
|
43
|
+
{"fields": ("quantity", "material_efficiency", "time_efficiency", "runs")},
|
|
44
|
+
),
|
|
45
|
+
(
|
|
46
|
+
"Timestamps",
|
|
47
|
+
{"fields": ("created_at", "last_updated"), "classes": ("collapse",)},
|
|
48
|
+
),
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@admin.register(IndustryJob)
|
|
53
|
+
class IndustryJobAdmin(admin.ModelAdmin):
|
|
54
|
+
list_display = [
|
|
55
|
+
"job_id",
|
|
56
|
+
"activity_name",
|
|
57
|
+
"blueprint_type_name",
|
|
58
|
+
"owner_user",
|
|
59
|
+
"character_id",
|
|
60
|
+
"status",
|
|
61
|
+
"runs",
|
|
62
|
+
"start_date",
|
|
63
|
+
"end_date",
|
|
64
|
+
]
|
|
65
|
+
list_filter = ["status", "activity_id", "owner_user", "character_id", "start_date"]
|
|
66
|
+
search_fields = [
|
|
67
|
+
"blueprint_type_name",
|
|
68
|
+
"product_type_name",
|
|
69
|
+
"activity_name",
|
|
70
|
+
"owner_user__username",
|
|
71
|
+
"job_id",
|
|
72
|
+
]
|
|
73
|
+
readonly_fields = ["job_id", "last_updated", "created_at", "start_date", "end_date"]
|
|
74
|
+
|
|
75
|
+
fieldsets = (
|
|
76
|
+
(
|
|
77
|
+
"Job Information",
|
|
78
|
+
{
|
|
79
|
+
"fields": (
|
|
80
|
+
"owner_user",
|
|
81
|
+
"character_id",
|
|
82
|
+
"job_id",
|
|
83
|
+
"installer_id",
|
|
84
|
+
"status",
|
|
85
|
+
)
|
|
86
|
+
},
|
|
87
|
+
),
|
|
88
|
+
(
|
|
89
|
+
"Activity Details",
|
|
90
|
+
{"fields": ("activity_id", "activity_name", "runs", "duration")},
|
|
91
|
+
),
|
|
92
|
+
(
|
|
93
|
+
"Blueprint Information",
|
|
94
|
+
{"fields": ("blueprint_id", "blueprint_type_id", "blueprint_type_name")},
|
|
95
|
+
),
|
|
96
|
+
("Product Information", {"fields": ("product_type_id", "product_type_name")}),
|
|
97
|
+
(
|
|
98
|
+
"Locations",
|
|
99
|
+
{
|
|
100
|
+
"fields": (
|
|
101
|
+
"facility_id",
|
|
102
|
+
"station_id",
|
|
103
|
+
"blueprint_location_id",
|
|
104
|
+
"output_location_id",
|
|
105
|
+
),
|
|
106
|
+
"classes": ("collapse",),
|
|
107
|
+
},
|
|
108
|
+
),
|
|
109
|
+
("Financial", {"fields": ("cost", "licensed_runs"), "classes": ("collapse",)}),
|
|
110
|
+
(
|
|
111
|
+
"Invention/Research",
|
|
112
|
+
{"fields": ("probability", "successful_runs"), "classes": ("collapse",)},
|
|
113
|
+
),
|
|
114
|
+
(
|
|
115
|
+
"Timestamps",
|
|
116
|
+
{
|
|
117
|
+
"fields": (
|
|
118
|
+
"start_date",
|
|
119
|
+
"end_date",
|
|
120
|
+
"pause_date",
|
|
121
|
+
"completed_date",
|
|
122
|
+
"created_at",
|
|
123
|
+
"last_updated",
|
|
124
|
+
),
|
|
125
|
+
"classes": ("collapse",),
|
|
126
|
+
},
|
|
127
|
+
),
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
@admin.register(CharacterUpdateTracker)
|
|
132
|
+
class CharacterUpdateTrackerAdmin(admin.ModelAdmin):
|
|
133
|
+
list_display = [
|
|
134
|
+
"user",
|
|
135
|
+
"character_id",
|
|
136
|
+
"blueprints_last_update",
|
|
137
|
+
"jobs_last_update",
|
|
138
|
+
"last_refresh_request",
|
|
139
|
+
"updated_at",
|
|
140
|
+
"has_error",
|
|
141
|
+
]
|
|
142
|
+
list_filter = [
|
|
143
|
+
"user",
|
|
144
|
+
"blueprints_last_update",
|
|
145
|
+
"jobs_last_update",
|
|
146
|
+
"last_refresh_request",
|
|
147
|
+
"updated_at",
|
|
148
|
+
]
|
|
149
|
+
search_fields = ["user__username", "character_id"]
|
|
150
|
+
readonly_fields = ["updated_at"]
|
|
151
|
+
|
|
152
|
+
@admin.display(
|
|
153
|
+
description="Has Error",
|
|
154
|
+
boolean=True,
|
|
155
|
+
)
|
|
156
|
+
def has_error(self, obj):
|
|
157
|
+
return bool(obj.last_error)
|
|
158
|
+
|
|
159
|
+
fieldsets = (
|
|
160
|
+
("Character Information", {"fields": ("user", "character_id")}),
|
|
161
|
+
(
|
|
162
|
+
"Update Status",
|
|
163
|
+
{
|
|
164
|
+
"fields": (
|
|
165
|
+
"blueprints_last_update",
|
|
166
|
+
"jobs_last_update",
|
|
167
|
+
"last_refresh_request",
|
|
168
|
+
"updated_at",
|
|
169
|
+
)
|
|
170
|
+
},
|
|
171
|
+
),
|
|
172
|
+
("Error Information", {"fields": ("last_error",), "classes": ("collapse",)}),
|
|
173
|
+
)
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Standard Library
|
|
2
|
+
import logging
|
|
3
|
+
import sys
|
|
4
|
+
from importlib import import_module
|
|
5
|
+
|
|
6
|
+
# Django
|
|
7
|
+
from django.apps import AppConfig, apps
|
|
8
|
+
from django.conf import settings
|
|
9
|
+
from django.db import connection
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class IndyHubConfig(AppConfig):
|
|
15
|
+
"""
|
|
16
|
+
Django application configuration for IndyHub.
|
|
17
|
+
|
|
18
|
+
Handles initialization of the application, including signal registration
|
|
19
|
+
and configuration of periodic tasks for industry data updates.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
name = "indy_hub"
|
|
23
|
+
verbose_name = "Indy Hub"
|
|
24
|
+
default_auto_field = "django.db.models.BigAutoField"
|
|
25
|
+
|
|
26
|
+
def ready(self):
|
|
27
|
+
"""
|
|
28
|
+
Initializes the application when Django starts.
|
|
29
|
+
|
|
30
|
+
This method:
|
|
31
|
+
1. Loads signal handlers for event processing
|
|
32
|
+
2. Sets up periodic tasks for automated industry data updates
|
|
33
|
+
3. Injects beat schedule for compatibility
|
|
34
|
+
"""
|
|
35
|
+
super().ready()
|
|
36
|
+
|
|
37
|
+
# Load signals
|
|
38
|
+
try:
|
|
39
|
+
import_module("indy_hub.signals")
|
|
40
|
+
logger.info("IndyHub signals loaded.")
|
|
41
|
+
except Exception as e:
|
|
42
|
+
logger.exception(f"Error loading signals: {e}")
|
|
43
|
+
|
|
44
|
+
# Skip tasks configuration during tests
|
|
45
|
+
if (
|
|
46
|
+
"test" in sys.argv
|
|
47
|
+
or "runtests.py" in sys.argv[0]
|
|
48
|
+
or hasattr(settings, "TESTING")
|
|
49
|
+
or "pytest" in sys.modules
|
|
50
|
+
):
|
|
51
|
+
logger.info("Skipping periodic tasks setup during tests.")
|
|
52
|
+
return
|
|
53
|
+
|
|
54
|
+
# Skip during migrations
|
|
55
|
+
if "migrate" in sys.argv or "makemigrations" in sys.argv:
|
|
56
|
+
logger.info("Skipping periodic tasks setup during migrations.")
|
|
57
|
+
return
|
|
58
|
+
|
|
59
|
+
# Check that Celery Beat tables exist
|
|
60
|
+
try:
|
|
61
|
+
with connection.cursor() as cursor:
|
|
62
|
+
cursor.execute(
|
|
63
|
+
"SELECT 1 FROM django_celery_beat_crontabschedule LIMIT 1"
|
|
64
|
+
)
|
|
65
|
+
except Exception as e:
|
|
66
|
+
logger.warning(
|
|
67
|
+
f"Celery Beat tables not available, skipping periodic tasks setup: {e}"
|
|
68
|
+
)
|
|
69
|
+
return
|
|
70
|
+
|
|
71
|
+
# Inject beat schedule for compatibility (optional, non-blocking)
|
|
72
|
+
try:
|
|
73
|
+
# AA Example App
|
|
74
|
+
from indy_hub.schedules import INDY_HUB_BEAT_SCHEDULE
|
|
75
|
+
|
|
76
|
+
if hasattr(settings, "CELERYBEAT_SCHEDULE"):
|
|
77
|
+
settings.CELERYBEAT_SCHEDULE.update(INDY_HUB_BEAT_SCHEDULE)
|
|
78
|
+
else:
|
|
79
|
+
settings.CELERYBEAT_SCHEDULE = INDY_HUB_BEAT_SCHEDULE.copy()
|
|
80
|
+
except Exception as e:
|
|
81
|
+
logger.warning(f"Could not inject indy_hub beat schedule: {e}")
|
|
82
|
+
|
|
83
|
+
# Configure periodic tasks
|
|
84
|
+
try:
|
|
85
|
+
from .tasks import setup_periodic_tasks
|
|
86
|
+
|
|
87
|
+
setup_periodic_tasks()
|
|
88
|
+
logger.info("IndyHub periodic tasks configured.")
|
|
89
|
+
except Exception as e:
|
|
90
|
+
logger.exception(f"Error setting up periodic tasks: {e}")
|
|
91
|
+
|
|
92
|
+
# Check dependencies (optional logging)
|
|
93
|
+
if not apps.is_installed("esi"):
|
|
94
|
+
logger.warning("ESI not installed; some features may be disabled.")
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Alliance Auth
|
|
2
|
+
from allianceauth import hooks
|
|
3
|
+
from allianceauth.services.hooks import MenuItemHook, UrlHook
|
|
4
|
+
|
|
5
|
+
from . import urls
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class IndyHubMenu(MenuItemHook):
|
|
9
|
+
"""
|
|
10
|
+
Adds a menu item for Indy Hub in Alliance Auth navigation.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
def __init__(self):
|
|
14
|
+
super().__init__(
|
|
15
|
+
"Indy Hub",
|
|
16
|
+
"fas fa-industry fa-fw",
|
|
17
|
+
"indy_hub:index",
|
|
18
|
+
navactive=[
|
|
19
|
+
"indy_hub:index",
|
|
20
|
+
"indy_hub:blueprints_list",
|
|
21
|
+
"indy_hub:jobs_list",
|
|
22
|
+
"indy_hub:token_management",
|
|
23
|
+
],
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
def render(self, request):
|
|
27
|
+
# Only show to authenticated users with the correct permission
|
|
28
|
+
if not request.user.is_authenticated:
|
|
29
|
+
return ""
|
|
30
|
+
if not request.user.has_perm("indy_hub.can_access_indy_hub"):
|
|
31
|
+
return ""
|
|
32
|
+
# Calculate pending copy requests count
|
|
33
|
+
try:
|
|
34
|
+
from .models import Blueprint, BlueprintCopyRequest
|
|
35
|
+
|
|
36
|
+
bps = Blueprint.objects.filter(owner_user=request.user, quantity=-1)
|
|
37
|
+
count = (
|
|
38
|
+
BlueprintCopyRequest.objects.filter(
|
|
39
|
+
type_id__in=bps.values_list("type_id", flat=True),
|
|
40
|
+
material_efficiency__in=bps.values_list(
|
|
41
|
+
"material_efficiency", flat=True
|
|
42
|
+
),
|
|
43
|
+
time_efficiency__in=bps.values_list("time_efficiency", flat=True),
|
|
44
|
+
fulfilled=False,
|
|
45
|
+
)
|
|
46
|
+
.exclude(requested_by=request.user)
|
|
47
|
+
.count()
|
|
48
|
+
)
|
|
49
|
+
self.count = count if count > 0 else None
|
|
50
|
+
except Exception:
|
|
51
|
+
self.count = None
|
|
52
|
+
# Delegate rendering to base class
|
|
53
|
+
return super().render(request)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@hooks.register("menu_item_hook")
|
|
57
|
+
def register_menu():
|
|
58
|
+
"""
|
|
59
|
+
Register the IndyHub menu item.
|
|
60
|
+
"""
|
|
61
|
+
return IndyHubMenu()
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@hooks.register("url_hook")
|
|
65
|
+
def register_urls():
|
|
66
|
+
"""
|
|
67
|
+
Register IndyHub URL patterns.
|
|
68
|
+
"""
|
|
69
|
+
return UrlHook(urls, "indy_hub", r"^indy_hub/")
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# indy_hub/decorators.py
|
|
2
|
+
# Standard Library
|
|
3
|
+
from functools import wraps
|
|
4
|
+
|
|
5
|
+
# Django
|
|
6
|
+
from django.contrib import messages
|
|
7
|
+
from django.shortcuts import redirect
|
|
8
|
+
|
|
9
|
+
# Import ESI Token only when needed to avoid import issues
|
|
10
|
+
try:
|
|
11
|
+
# Alliance Auth
|
|
12
|
+
from esi.models import Token
|
|
13
|
+
except ImportError:
|
|
14
|
+
Token = None
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def token_required(scopes=None):
|
|
18
|
+
"""
|
|
19
|
+
Decorator that checks if the user has valid ESI tokens with required scopes.
|
|
20
|
+
If not, redirects to token authorization page.
|
|
21
|
+
"""
|
|
22
|
+
if scopes is None:
|
|
23
|
+
scopes = []
|
|
24
|
+
|
|
25
|
+
def decorator(view_func):
|
|
26
|
+
@wraps(view_func)
|
|
27
|
+
def _wrapped_view(request, *args, **kwargs):
|
|
28
|
+
if not request.user.is_authenticated:
|
|
29
|
+
return redirect("auth_login_user")
|
|
30
|
+
|
|
31
|
+
# Check if user has tokens with required scopes
|
|
32
|
+
if Token:
|
|
33
|
+
try:
|
|
34
|
+
tokens = Token.objects.filter(user=request.user).require_scopes(
|
|
35
|
+
scopes
|
|
36
|
+
)
|
|
37
|
+
if not tokens.exists():
|
|
38
|
+
# User doesn't have tokens with required scopes
|
|
39
|
+
scope_names = ", ".join(scopes)
|
|
40
|
+
messages.warning(
|
|
41
|
+
request,
|
|
42
|
+
f"You need to authorize ESI access with the following scopes: {scope_names}",
|
|
43
|
+
)
|
|
44
|
+
return redirect("indy_hub:token_management")
|
|
45
|
+
except Exception as e:
|
|
46
|
+
messages.error(request, f"Error checking ESI tokens: {e}")
|
|
47
|
+
return redirect("indy_hub:token_management")
|
|
48
|
+
else:
|
|
49
|
+
messages.error(request, "ESI module not available")
|
|
50
|
+
return redirect("indy_hub:index")
|
|
51
|
+
|
|
52
|
+
return view_func(request, *args, **kwargs)
|
|
53
|
+
|
|
54
|
+
return _wrapped_view
|
|
55
|
+
|
|
56
|
+
return decorator
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def blueprints_token_required(view_func):
|
|
60
|
+
"""Decorator specifically for blueprint views."""
|
|
61
|
+
return token_required(["esi-characters.read_blueprints.v1"])(view_func)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def industry_jobs_token_required(view_func):
|
|
65
|
+
"""Decorator specifically for industry jobs views."""
|
|
66
|
+
return token_required(["esi-industry.read_character_jobs.v1"])(view_func)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def indy_hub_access_required(view_func):
|
|
70
|
+
@wraps(view_func)
|
|
71
|
+
def _wrapped_view(request, *args, **kwargs):
|
|
72
|
+
if not request.user.is_authenticated:
|
|
73
|
+
return redirect("auth_login_user")
|
|
74
|
+
if not request.user.has_perm("indy_hub.can_access_indy_hub"):
|
|
75
|
+
messages.error(request, "You do not have permission to access Indy Hub.")
|
|
76
|
+
return redirect("indy_hub:index")
|
|
77
|
+
return view_func(request, *args, **kwargs)
|
|
78
|
+
|
|
79
|
+
return _wrapped_view
|