import os from github import Github import requests import random import string def create_github_repo(token, repo_name, private=False): """إنشاء ريبوزيتوري جديد على GitHub مع التحقق من الاسم الفريد""" g = Github(token) user = g.get_user() # Try to create repo with original name original_name = repo_name counter = 1 max_attempts = 100 # Allow up to 100 attempts (my-website-1 through my-website-100) for attempt in range(max_attempts): try: repo = user.create_repo(repo_name, private=private) return repo except Exception as e: error_str = str(e) # Check if error is due to name already existing if "name already exists" in error_str or "422" in error_str: # Add number suffix: (1), (2), (3), etc. repo_name = f"{original_name}-{counter}" counter += 1 else: # Check for 404 which usually means scope issues if "404" in error_str: raise Exception("GitHub API returned 404 (Not Found). This usually means your Token lacks the 'repo' scope or 'Administration' write permission. Please ensure your token has full repo access.") # Different error, re-raise raise # If all attempts failed, raise the last exception raise Exception(f"Failed to create repository after {max_attempts} attempts") def upload_files_to_repo(repo, local_dir, branch="main"): """رفع كل الملفات من مجلد محلي إلى الريبو (يدعم التحديث)""" for root, _, files in os.walk(local_dir): for file_name in files: full_path = os.path.join(root, file_name) with open(full_path, "rb") as f: content = f.read() relative_path = os.path.relpath(full_path, local_dir).replace("\\", "/") try: # Check if file exists to update it contents = repo.get_contents(relative_path, ref=branch) repo.update_file( path=relative_path, message=f"Update {relative_path}", content=content, sha=contents.sha, branch=branch ) print(f"✓ Updated {relative_path}") except Exception as e: # If not found (404), create it if "404" in str(e) or "Not Found" in str(e): repo.create_file( path=relative_path, message=f"Add {relative_path}", content=content, branch=branch ) print(f"✓ Created {relative_path}") else: print(f"⚠ Error with {relative_path}: {e}") def enable_github_pages(username, repo_name, token): """تفعيل GitHub Pages""" pages_url = f"https://api.github.com/repos/{username}/{repo_name}/pages" headers = { "Authorization": f"token {token}", "Accept": "application/vnd.github.v3+json" } payload = {"source": {"branch": "main", "path": "/"}} response = requests.post(pages_url, headers=headers, json=payload) return response.status_code in [201, 204] def get_repository(username, repo_name, token): """ Retrieve an existing GitHub repository. Args: username: GitHub username repo_name: Repository name token: GitHub personal access token Returns: Repository object or None if not found """ try: g = Github(token) repo = g.get_repo(f"{username}/{repo_name}") return repo except Exception as e: print(f"⚠ Repository not found: {e}") return None def update_file_in_repo(repo, file_path, content, commit_message="Update file"): """ Update an existing file in the repository. Args: repo: Repository object file_path: Path to file in repository (e.g., "index.html") content: New file content (string or bytes) commit_message: Commit message Returns: True if successful, False otherwise """ try: # Get the file from the repository file = repo.get_contents(file_path) # Update the file repo.update_file( path=file_path, message=commit_message, content=content, sha=file.sha, branch="main" ) print(f"✓ Updated {file_path} in repository") return True except Exception as e: print(f"⚠ Error updating file: {e}") return False def resync_webcraft_file(username, repo_name, token, html_file_path, commit_message="Resync from WebCraft"): """ Resync WebCraft HTML file with existing GitHub repository. Args: username: GitHub username repo_name: Repository name token: GitHub personal access token html_file_path: Path to local HTML file commit_message: Commit message for the update Returns: dict with status and URL, or error message """ try: # Get the repository repo = get_repository(username, repo_name, token) if not repo: return { "status": "error", "message": f"Repository '{repo_name}' not found" } # Read the HTML file with open(html_file_path, 'rb') as f: content = f.read() # Find the HTML file in the repository (usually index.html) filename = os.path.basename(html_file_path) # Update the file if update_file_in_repo(repo, filename, content, commit_message): site_url = f"https://{username}.github.io/{repo_name}/" return { "status": "success", "message": "Repository synced successfully", "website_url": site_url, "repo_url": repo.html_url } else: return { "status": "error", "message": "Failed to update file in repository" } except Exception as e: return { "status": "error", "message": str(e) }