import re import json import requests from packaging import version import sys from datetime import datetime import os import subprocess import tempfile from requests.exceptions import RequestException import time VERSIONS_JSON_FILE = "versions_deb.json" SPOTIFY_REPO_URL = ( "https://repository-origin.spotify.com/pool/non-free/s/spotify-client/" ) REPO_UPLOAD = "LoaderSpot/deb-builds" def get_spotify_versions_from_repo(): urls = [ "https://repository.spotify.com/dists/testing/non-free/binary-amd64/Packages", SPOTIFY_REPO_URL, ] version_pattern = r"(\d+\.\d+\.\d+\.\d+\.g[0-9a-f]{8})" versions = set() for url in urls: try: response = requests.get(url) response.raise_for_status() found_versions = re.findall(version_pattern, response.text) versions.update(found_versions) except requests.exceptions.RequestException as e: print(f"Ошибка при запросе {url}: {e}") min_version = version.parse("1.1.58") return [ v for v in versions if version.parse(".".join(v.split(".")[:3])) > min_version ] def get_existing_versions(): try: with open(VERSIONS_JSON_FILE, "r", encoding="utf-8") as f: return json.load(f) except (FileNotFoundError, json.JSONDecodeError) as e: print(f"Ошибка при чтении файла {VERSIONS_JSON_FILE}: {e}") return {} def parse_version_key(full_version): match = re.match(r"(\d+\.\d+\.\d+\.\d+)\..*", full_version) return match.group(1) if match else None def find_new_versions(repo_versions, existing_data): new_versions = [] for full_version in repo_versions: version_key = parse_version_key(full_version) if version_key and version_key not in existing_data: new_versions.append((version_key, full_version)) return new_versions def get_file_info(full_version): url = f"{SPOTIFY_REPO_URL}spotify-client_{full_version}_amd64.deb" try: response = requests.head(url, timeout=10) if response.status_code == 200: size = response.headers.get("Content-Length", "0") last_modified = response.headers.get("Last-Modified", "") if last_modified: date_obj = datetime.strptime(last_modified, "%a, %d %b %Y %H:%M:%S %Z") formatted_date = date_obj.strftime("%d.%m.%Y") else: formatted_date = "" return {"size": size, "data": formatted_date} else: print(f"Ошибка HEAD запроса к {url}: {response.status_code}") except Exception as e: print(f"Ошибка при запросе информации о файле: {e}") return {"size": "0", "data": ""} def sort_versions(versions_dict): def version_key(item): return tuple(map(int, item[0].split("."))) return dict(sorted(versions_dict.items(), key=version_key, reverse=True)) def update_json_file(sorted_data): try: with open(VERSIONS_JSON_FILE, "w", encoding="utf-8") as f: json.dump(sorted_data, f, indent=2) print(f"Файл {VERSIONS_JSON_FILE} успешно обновлен") return True except Exception as e: print(f"Ошибка при обновлении файла {VERSIONS_JSON_FILE}: {e}") return False def commit_changes(new_versions): try: github_actions = os.environ.get("GITHUB_ACTIONS") == "true" if github_actions: subprocess.run(["git", "config", "--global", "user.name", "GitHub Actions"]) subprocess.run( ["git", "config", "--global", "user.email", "actions@github.com"] ) subprocess.run(["git", "add", VERSIONS_JSON_FILE]) # Формируем сообщение коммита в зависимости от количества новых версий if new_versions: commit_message = ( f"Added deb version {new_versions[0][0]}" if len(new_versions) == 1 else f"Added deb versions: {', '.join(v[0] for v in new_versions)}" ) else: commit_message = "Update Spotify versions" # Создаем коммит subprocess.run(["git", "commit", "-m", commit_message]) if github_actions: token = get_github_token() if token: repo_url = f"https://{token}@github.com/{os.environ.get('GITHUB_REPOSITORY')}.git" subprocess.run(["git", "push", repo_url, "HEAD:main"]) else: subprocess.run(["git", "push"]) else: subprocess.run(["git", "push"]) print("Изменения успешно отправлены в репозиторий") return True except Exception as e: print(f"Ошибка при отправке изменений в репозиторий: {e}") return False def download_deb_file(full_version): url = f"{SPOTIFY_REPO_URL}spotify-client_{full_version}_amd64.deb" filename = f"spotify-client_{full_version}_amd64.deb" try: print(f"Скачивание {filename}...") with tempfile.NamedTemporaryFile(delete=False, suffix=".deb") as temp_file: response = requests.get(url, stream=True, timeout=60) response.raise_for_status() for chunk in response.iter_content(chunk_size=8192): if chunk: temp_file.write(chunk) return temp_file.name, filename except RequestException as e: print(f"Ошибка при скачивании файла: {e}") return None, None def get_github_token(): token = os.environ.get("PERSONAL_TOKEN") if not token: print("ОШИБКА: Не найден PERSONAL_TOKEN в переменных окружения") return token def get_latest_release(token): headers = { "Authorization": f"token {token}", "Accept": "application/vnd.github.v3+json", } url = f"https://api.github.com/repos/{REPO_UPLOAD}/releases/latest" try: response = requests.get(url, headers=headers) response.raise_for_status() return response.json() except RequestException as e: print(f"Ошибка при получении последнего релиза: {e}") return None def upload_file_to_release(token, release_id, file_path, file_name): headers = { "Authorization": f"token {token}", "Accept": "application/vnd.github.v3+json", "Content-Type": "application/octet-stream", } url = f"https://uploads.github.com/repos/{REPO_UPLOAD}/releases/{release_id}/assets?name={file_name}" try: with open(file_path, "rb") as file: print(f"Загрузка {file_name} в релиз...") response = requests.post(url, headers=headers, data=file) response.raise_for_status() print(f"Файл {file_name} успешно загружен в релиз") return True except RequestException as e: print(f"Ошибка при загрузке файла в релиз: {e}") return False finally: # Удаляем временный файл try: os.remove(file_path) except Exception as e: print(f"Не удалось удалить временный файл {file_path}: {e}") def main(): # Получаем версии из репозитория Spotify spotify_versions = get_spotify_versions_from_repo() # Получаем существующие версии из JSON existing_data = get_existing_versions() # Находим новые версии new_versions = find_new_versions(spotify_versions, existing_data) if not new_versions: print("Новых версий не найдено") return False print(f"Найдено новых версий: {len(new_versions)}") # Если есть новые версии, получаем токен GitHub и загружаем файлы github_token = get_github_token() if github_token: latest_release = get_latest_release(github_token) if latest_release: release_id = latest_release["id"] # Скачиваем и загружаем каждую новую версию for version_key, full_version in new_versions: temp_file_path, file_name = download_deb_file(full_version) if temp_file_path: time.sleep(2) upload_file_to_release( github_token, release_id, temp_file_path, file_name ) # Добавляем новые версии в существующие данные for version_key, full_version in new_versions: file_info = get_file_info(full_version) existing_data[version_key] = { "fullversion": full_version, "size": file_info["size"], "data": file_info["data"], "links": { "amd64": f"https://github.com/LoaderSpot/deb-builds/releases/download/builds/spotify-client_{full_version}_amd64.deb" }, } # Сортируем и обновляем данные sorted_data = sort_versions(existing_data) if update_json_file(sorted_data): # Если мы находимся в GitHub Actions, выполняем коммит if os.environ.get("GITHUB_ACTIONS") == "true": commit_changes(new_versions) print("Обновление выполнено успешно") return True if __name__ == "__main__": main() sys.exit(0)