- Allow and improve viewing of different content types. First type implemented: changelog
This commit is contained in:
@@ -11,6 +11,7 @@ from flask_restx import Api
|
||||
from prometheus_flask_exporter import PrometheusMetrics
|
||||
|
||||
from .utils.cache.eveai_cache_manager import EveAICacheManager
|
||||
from .utils.content_utils import ContentManager
|
||||
from .utils.simple_encryption import SimpleEncryption
|
||||
from .utils.minio_utils import MinioClient
|
||||
|
||||
@@ -30,4 +31,5 @@ simple_encryption = SimpleEncryption()
|
||||
minio_client = MinioClient()
|
||||
metrics = PrometheusMetrics.for_app_factory()
|
||||
cache_manager = EveAICacheManager()
|
||||
content_manager = ContentManager()
|
||||
|
||||
|
||||
215
common/utils/content_utils.py
Normal file
215
common/utils/content_utils.py
Normal file
@@ -0,0 +1,215 @@
|
||||
import os
|
||||
import re
|
||||
import logging
|
||||
from packaging import version
|
||||
from flask import current_app
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class ContentManager:
|
||||
def __init__(self, app=None):
|
||||
self.app = app
|
||||
if app:
|
||||
self.init_app(app)
|
||||
|
||||
def init_app(self, app):
|
||||
self.app = app
|
||||
|
||||
# Controleer of het pad bestaat
|
||||
if not os.path.exists(app.config['CONTENT_DIR']):
|
||||
logger.warning(f"Content directory not found at: {app.config['CONTENT_DIR']}")
|
||||
else:
|
||||
logger.info(f"Content directory configured at: {app.config['CONTENT_DIR']}")
|
||||
|
||||
def get_content_path(self, content_type, major_minor=None, patch=None):
|
||||
"""
|
||||
Geef het volledige pad naar een contentbestand
|
||||
|
||||
Args:
|
||||
content_type (str): Type content (bv. 'changelog', 'terms')
|
||||
major_minor (str, optional): Major.Minor versie (bv. '1.0')
|
||||
patch (str, optional): Patchnummer (bv. '5')
|
||||
|
||||
Returns:
|
||||
str: Volledige pad naar de content map of bestand
|
||||
"""
|
||||
content_path = os.path.join(self.app.config['CONTENT_DIR'], content_type)
|
||||
|
||||
if major_minor:
|
||||
content_path = os.path.join(content_path, major_minor)
|
||||
|
||||
if patch:
|
||||
content_path = os.path.join(content_path, f"{major_minor}.{patch}.md")
|
||||
|
||||
return content_path
|
||||
|
||||
def _parse_version(self, filename):
|
||||
"""Parse een versienummer uit een bestandsnaam"""
|
||||
match = re.match(r'(\d+\.\d+)\.(\d+)\.md', filename)
|
||||
if match:
|
||||
return match.group(1), match.group(2)
|
||||
return None, None
|
||||
|
||||
def get_latest_version(self, content_type, major_minor=None):
|
||||
"""
|
||||
Verkrijg de laatste versie van een bepaald contenttype
|
||||
|
||||
Args:
|
||||
content_type (str): Type content (bv. 'changelog', 'terms')
|
||||
major_minor (str, optional): Specifieke major.minor versie, anders de hoogste
|
||||
|
||||
Returns:
|
||||
tuple: (major_minor, patch, full_version) of None als niet gevonden
|
||||
"""
|
||||
try:
|
||||
# Basispad voor dit contenttype
|
||||
content_path = os.path.join(self.app.config['CONTENT_DIR'], content_type)
|
||||
|
||||
if not os.path.exists(content_path):
|
||||
logger.error(f"Content path does not exist: {content_path}")
|
||||
return None
|
||||
|
||||
# Als geen major_minor opgegeven, vind de hoogste
|
||||
if not major_minor:
|
||||
available_versions = os.listdir(content_path)
|
||||
if not available_versions:
|
||||
return None
|
||||
|
||||
# Sorteer op versienummer (major.minor)
|
||||
available_versions.sort(key=lambda v: version.parse(v))
|
||||
major_minor = available_versions[-1]
|
||||
|
||||
# Nu we major_minor hebben, zoek de hoogste patch
|
||||
major_minor_path = os.path.join(content_path, major_minor)
|
||||
|
||||
if not os.path.exists(major_minor_path):
|
||||
logger.error(f"Version path does not exist: {major_minor_path}")
|
||||
return None
|
||||
|
||||
files = os.listdir(major_minor_path)
|
||||
version_files = []
|
||||
|
||||
for file in files:
|
||||
mm, p = self._parse_version(file)
|
||||
if mm == major_minor and p:
|
||||
version_files.append((mm, p, f"{mm}.{p}"))
|
||||
|
||||
if not version_files:
|
||||
return None
|
||||
|
||||
# Sorteer op patch nummer
|
||||
version_files.sort(key=lambda v: int(v[1]))
|
||||
return version_files[-1]
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error finding latest version for {content_type}: {str(e)}")
|
||||
return None
|
||||
|
||||
def read_content(self, content_type, major_minor=None, patch=None):
|
||||
"""
|
||||
Lees content met versieondersteuning
|
||||
|
||||
Als major_minor en patch niet zijn opgegeven, wordt de laatste versie gebruikt.
|
||||
Als alleen major_minor is opgegeven, wordt de laatste patch van die versie gebruikt.
|
||||
|
||||
Args:
|
||||
content_type (str): Type content (bv. 'changelog', 'terms')
|
||||
major_minor (str, optional): Major.Minor versie (bv. '1.0')
|
||||
patch (str, optional): Patchnummer (bv. '5')
|
||||
|
||||
Returns:
|
||||
dict: {
|
||||
'content': str,
|
||||
'version': str,
|
||||
'content_type': str
|
||||
} of None bij fout
|
||||
"""
|
||||
try:
|
||||
# Als geen versie opgegeven, vind de laatste
|
||||
if not major_minor:
|
||||
version_info = self.get_latest_version(content_type)
|
||||
if not version_info:
|
||||
logger.error(f"No versions found for {content_type}")
|
||||
return None
|
||||
|
||||
major_minor, patch, full_version = version_info
|
||||
|
||||
# Als geen patch opgegeven, vind de laatste patch voor deze major_minor
|
||||
elif not patch:
|
||||
version_info = self.get_latest_version(content_type, major_minor)
|
||||
if not version_info:
|
||||
logger.error(f"No versions found for {content_type} {major_minor}")
|
||||
return None
|
||||
|
||||
major_minor, patch, full_version = version_info
|
||||
else:
|
||||
full_version = f"{major_minor}.{patch}"
|
||||
|
||||
# Nu hebben we major_minor en patch, lees het bestand
|
||||
file_path = self.get_content_path(content_type, major_minor, patch)
|
||||
|
||||
if not os.path.exists(file_path):
|
||||
logger.error(f"Content file does not exist: {file_path}")
|
||||
return None
|
||||
|
||||
with open(file_path, 'r', encoding='utf-8') as file:
|
||||
content = file.read()
|
||||
|
||||
return {
|
||||
'content': content,
|
||||
'version': full_version,
|
||||
'content_type': content_type
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error reading content {content_type} {major_minor}.{patch}: {str(e)}")
|
||||
return None
|
||||
|
||||
def list_content_types(self):
|
||||
"""Lijst alle beschikbare contenttypes op"""
|
||||
try:
|
||||
return [d for d in os.listdir(self.app.config['CONTENT_DIR'])
|
||||
if os.path.isdir(os.path.join(self.app.config['CONTENT_DIR'], d))]
|
||||
except Exception as e:
|
||||
logger.error(f"Error listing content types: {str(e)}")
|
||||
return []
|
||||
|
||||
def list_versions(self, content_type):
|
||||
"""
|
||||
Lijst alle beschikbare versies voor een contenttype
|
||||
|
||||
Returns:
|
||||
list: Lijst van dicts met versie-informatie
|
||||
[{'version': '1.0.0', 'path': '/path/to/file', 'date_modified': datetime}]
|
||||
"""
|
||||
versions = []
|
||||
try:
|
||||
content_path = os.path.join(self.app.config['CONTENT_DIR'], content_type)
|
||||
|
||||
if not os.path.exists(content_path):
|
||||
return []
|
||||
|
||||
for major_minor in os.listdir(content_path):
|
||||
major_minor_path = os.path.join(content_path, major_minor)
|
||||
|
||||
if not os.path.isdir(major_minor_path):
|
||||
continue
|
||||
|
||||
for file in os.listdir(major_minor_path):
|
||||
mm, p = self._parse_version(file)
|
||||
if mm and p:
|
||||
file_path = os.path.join(major_minor_path, file)
|
||||
mod_time = os.path.getmtime(file_path)
|
||||
versions.append({
|
||||
'version': f"{mm}.{p}",
|
||||
'path': file_path,
|
||||
'date_modified': mod_time
|
||||
})
|
||||
|
||||
# Sorteer op versienummer
|
||||
versions.sort(key=lambda v: version.parse(v['version']))
|
||||
return versions
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error listing versions for {content_type}: {str(e)}")
|
||||
return []
|
||||
Reference in New Issue
Block a user