mirror of
https://github.com/soxoj/maigret.git
synced 2026-05-07 06:24:35 +00:00
Add automated solution for closing invalid Telegram PRs
Co-authored-by: soxoj <31013580+soxoj@users.noreply.github.com>
This commit is contained in:
Executable
+205
@@ -0,0 +1,205 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Utility script to close pull requests with titles matching "Invalid result https://t.me/..."
|
||||
|
||||
This script identifies and closes PRs that follow the pattern of invalid telegram results,
|
||||
which are typically auto-generated or spam PRs that should not be processed.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from typing import List, Optional
|
||||
|
||||
try:
|
||||
import requests
|
||||
except ImportError:
|
||||
print("Error: requests library is required. Install with: pip install requests")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
class GitHubAPI:
|
||||
"""Simple GitHub API wrapper for managing pull requests."""
|
||||
|
||||
def __init__(self, token: str, owner: str, repo: str):
|
||||
self.token = token
|
||||
self.owner = owner
|
||||
self.repo = repo
|
||||
self.base_url = "https://api.github.com"
|
||||
self.headers = {
|
||||
"Authorization": f"token {token}",
|
||||
"Accept": "application/vnd.github.v3+json"
|
||||
}
|
||||
|
||||
def get_open_prs(self) -> List[dict]:
|
||||
"""Get all open pull requests."""
|
||||
url = f"{self.base_url}/repos/{self.owner}/{self.repo}/pulls"
|
||||
params = {"state": "open", "per_page": 100}
|
||||
|
||||
all_prs = []
|
||||
page = 1
|
||||
|
||||
while True:
|
||||
params["page"] = page
|
||||
response = requests.get(url, headers=self.headers, params=params)
|
||||
response.raise_for_status()
|
||||
|
||||
prs = response.json()
|
||||
if not prs:
|
||||
break
|
||||
|
||||
all_prs.extend(prs)
|
||||
page += 1
|
||||
|
||||
return all_prs
|
||||
|
||||
def close_pr(self, pr_number: int, comment: Optional[str] = None) -> bool:
|
||||
"""Close a pull request with an optional comment."""
|
||||
try:
|
||||
# Add comment if provided
|
||||
if comment:
|
||||
comment_url = f"{self.base_url}/repos/{self.owner}/{self.repo}/issues/{pr_number}/comments"
|
||||
comment_data = {"body": comment}
|
||||
response = requests.post(comment_url, headers=self.headers, json=comment_data)
|
||||
response.raise_for_status()
|
||||
|
||||
# Close the PR
|
||||
close_url = f"{self.base_url}/repos/{self.owner}/{self.repo}/pulls/{pr_number}"
|
||||
close_data = {"state": "closed"}
|
||||
response = requests.patch(close_url, headers=self.headers, json=close_data)
|
||||
response.raise_for_status()
|
||||
|
||||
return True
|
||||
except requests.RequestException as e:
|
||||
print(f"Error closing PR #{pr_number}: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def is_invalid_telegram_pr(title: str) -> bool:
|
||||
"""
|
||||
Check if a PR title matches the pattern "Invalid result https://t.me/..."
|
||||
|
||||
Args:
|
||||
title: The PR title to check
|
||||
|
||||
Returns:
|
||||
True if the title matches the pattern, False otherwise
|
||||
"""
|
||||
# Pattern: "Invalid result https://t.me/..." (case insensitive)
|
||||
pattern = r"^invalid\s+result\s+https://t\.me/.*"
|
||||
return bool(re.match(pattern, title.strip(), re.IGNORECASE))
|
||||
|
||||
|
||||
def find_invalid_telegram_prs(github_api: GitHubAPI) -> List[dict]:
|
||||
"""
|
||||
Find all open PRs that match the invalid telegram pattern.
|
||||
|
||||
Args:
|
||||
github_api: GitHub API wrapper instance
|
||||
|
||||
Returns:
|
||||
List of PR dictionaries that match the pattern
|
||||
"""
|
||||
all_prs = github_api.get_open_prs()
|
||||
matching_prs = []
|
||||
|
||||
for pr in all_prs:
|
||||
if is_invalid_telegram_pr(pr["title"]):
|
||||
matching_prs.append(pr)
|
||||
|
||||
return matching_prs
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function to find and close invalid telegram PRs."""
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Close pull requests with titles matching 'Invalid result https://t.me/...'"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--token",
|
||||
required=False,
|
||||
help="GitHub personal access token (or set GITHUB_TOKEN env var)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--owner",
|
||||
default="soxoj",
|
||||
help="Repository owner (default: soxoj)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--repo",
|
||||
default="maigret",
|
||||
help="Repository name (default: maigret)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--dry-run",
|
||||
action="store_true",
|
||||
help="Show what would be closed without actually closing PRs"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--comment",
|
||||
default="Automatically closing this PR as it appears to be an invalid result for a Telegram URL. "
|
||||
"If this is a legitimate PR, please reopen it with a more descriptive title.",
|
||||
help="Comment to add when closing PRs"
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Get GitHub token
|
||||
token = args.token or os.getenv("GITHUB_TOKEN")
|
||||
if not token:
|
||||
print("Error: GitHub token is required. Provide via --token or GITHUB_TOKEN env var")
|
||||
sys.exit(1)
|
||||
|
||||
# Initialize GitHub API
|
||||
try:
|
||||
github_api = GitHubAPI(token, args.owner, args.repo)
|
||||
except Exception as e:
|
||||
print(f"Error initializing GitHub API: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
# Find matching PRs
|
||||
print(f"Searching for PRs matching pattern in {args.owner}/{args.repo}...")
|
||||
try:
|
||||
matching_prs = find_invalid_telegram_prs(github_api)
|
||||
except Exception as e:
|
||||
print(f"Error fetching PRs: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
if not matching_prs:
|
||||
print("No PRs found matching the pattern 'Invalid result https://t.me/...'")
|
||||
return
|
||||
|
||||
print(f"Found {len(matching_prs)} PR(s) matching the pattern:")
|
||||
|
||||
for pr in matching_prs:
|
||||
print(f" - PR #{pr['number']}: {pr['title']}")
|
||||
print(f" Created by: {pr['user']['login']}")
|
||||
print(f" URL: {pr['html_url']}")
|
||||
print()
|
||||
|
||||
if args.dry_run:
|
||||
print("Dry run mode: No PRs were actually closed.")
|
||||
return
|
||||
|
||||
# Confirm before closing
|
||||
response = input(f"Close {len(matching_prs)} PR(s)? [y/N]: ")
|
||||
if response.lower() != 'y':
|
||||
print("Cancelled.")
|
||||
return
|
||||
|
||||
# Close PRs
|
||||
closed_count = 0
|
||||
for pr in matching_prs:
|
||||
print(f"Closing PR #{pr['number']}: {pr['title']}")
|
||||
if github_api.close_pr(pr['number'], args.comment):
|
||||
closed_count += 1
|
||||
print(f" ✓ Closed successfully")
|
||||
else:
|
||||
print(f" ✗ Failed to close")
|
||||
|
||||
print(f"\nClosed {closed_count} out of {len(matching_prs)} PRs.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user