import os import requests import re from bs4 import BeautifulSoup import subprocess import time import logging # Configure logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # === Configuration === REDMINE_URL = "https://redmine.maketank.net" # e.g., https://redmine.example.com REDMINE_API_KEY = "62120b7ed6bf84023b2a1d7d5a265cf172f8d607" PROJECT_ID = "bastelstube" # e.g., "my-project" GITEA_WIKI_URL = "https://git.maketank.net:2222/chaos/spielplatz.wiki.git" # Gitea wiki Git URL GITEA_USERNAME = "do" GITEA_TOKEN = "2d2be00637182c6d5411512f456218ee59fa1f81" # Use a personal access token # Optional: Gitea API for creating pages (if you want to use it instead of Git) # GITEA_API_URL = "https://gitea.example.com/api/v1" # === Functions === def redmine_get_wiki_pages(): """Get all wiki pages from Redmine project""" url = f"{REDMINE_URL}/projects/{PROJECT_ID}/wiki.xml" headers = {"X-Redmine-API-Key": REDMINE_API_KEY} response = requests.get(url, headers=headers) response.raise_for_status() soup = BeautifulSoup(response.content, "xml") pages = [] for page in soup.find_all("wiki-page"): title = page.find("title").text content = page.find("content").text pages.append({"title": title, "content": content}) logger.info(f"Found page: {title}") return pages def redmine_markup_to_markdown(content): """Convert Redmine wiki markup to Markdown""" # Replace Redmine-specific syntax to Markdown # Note: This is a simplified converter. You may need to extend it. # Convert bold content = re.sub(r'\*\*(.*?)\*\*', r'**\1**', content) content = re.sub(r'\*(.*?)\*', r'*\1*', content) # Convert headings content = re.sub(r'={2,}(.*?)={2,}', r'# \1', content) content = re.sub(r'={1,}(.*?)={1,}', r'## \1', content) # Convert lists content = re.sub(r'^\s*\* (.*?)$', r'- \1', content, flags=re.MULTILINE) content = re.sub(r'^\s*\# (.*?)$', r'1. \1', content, flags=re.MULTILINE) # Convert links content = re.sub(r'\[\[(.*?)\]\]', r'[\1](\1)', content) # Simple link content = re.sub(r'\[(.*?)\](.*?)\]', r'[\1](\2)', content) # [text](url) # Convert images content = re.sub(r'!\[(.*?)\]\((.*?)\)', r'![](\2)', content) # Convert code blocks content = re.sub(r'
(.*?)
', r'```python\n\1\n```', content, flags=re.DOTALL) # Remove HTML tags (if any) content = re.sub(r'<[^>]+>', '', content) return content def clone_or_init_wiki_repo(repo_url, local_dir): """Clone or initialize the Gitea wiki repo""" if not os.path.exists(local_dir): logger.info(f"Cloning Gitea wiki repository: {repo_url}") subprocess.run(["git", "clone", repo_url, local_dir], check=True) else: logger.info(f"Using existing local wiki repo: {local_dir}") os.chdir(local_dir) subprocess.run(["git", "pull"], check=True) return local_dir def push_to_gitea_wiki(local_dir, pages): """Add pages as Markdown files and push to Gitea""" os.chdir(local_dir) # Create pages as .md files for page in pages: filename = f"{page['title'].replace(' ', '_')}.md" filepath = os.path.join(local_dir, filename) # Convert content to Markdown markdown_content = redmine_markup_to_markdown(page['content']) # Write to file with open(filepath, 'w', encoding='utf-8') as f: f.write(f"# {page['title']}\n\n") f.write(markdown_content) logger.info(f"Saved page: {filename}") # Add, commit, and push subprocess.run(["git", "add", "."], check=True) subprocess.run(["git", "commit", "-m", "Import Redmine wiki pages"], check=True) subprocess.run(["git", "push", "origin", "master"], check=True) logger.info("✅ Wiki pages pushed to Gitea!") def main(): # Step 1: Get wiki pages from Redmine logger.info("Fetching Redmine wiki pages...") pages = redmine_get_wiki_pages() # Step 2: Prepare local directory for Gitea wiki local_wiki_dir = "gitea_wiki_clone" clone_or_init_wiki_repo(GITEA_WIKI_URL, local_wiki_dir) # Step 3: Push pages to Gitea push_to_gitea_wiki(local_wiki_dir, pages) if __name__ == "__main__": main()