149 lines
3.9 KiB
Python
149 lines
3.9 KiB
Python
import asyncio
|
|
import datetime
|
|
import logging
|
|
import subprocess
|
|
from pathlib import Path
|
|
import json
|
|
import aiohttp
|
|
from nio import (
|
|
AsyncClient,
|
|
JoinResponse,
|
|
)
|
|
|
|
from matrix_bot.gitea import (
|
|
GiteaData,
|
|
)
|
|
|
|
from .matrix import MatrixData, send_message
|
|
from .openai import create_jsonl_file, upload_and_process_file
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
def write_file_with_date_prefix(content: str, directory: Path, suffix: str) -> Path:
|
|
"""
|
|
Write content to a file with the current date as filename prefix.
|
|
|
|
:param content: The content to write to the file.
|
|
:param directory: The directory where the file will be saved.
|
|
:return: The path to the created file.
|
|
"""
|
|
# Ensure the directory exists
|
|
directory.mkdir(parents=True, exist_ok=True)
|
|
|
|
# Get the current date
|
|
current_date = datetime.datetime.now().strftime("%Y-%m-%d")
|
|
|
|
# Create the filename
|
|
filename = f"{current_date}_{suffix}.txt"
|
|
file_path = directory / filename
|
|
|
|
# Write the content to the file
|
|
with open(file_path, "w") as file:
|
|
file.write(content)
|
|
|
|
return file_path
|
|
|
|
|
|
async def git_pull(repo_path: Path) -> None:
|
|
cmd = ["git", "pull"]
|
|
process = await asyncio.create_subprocess_exec(
|
|
*cmd,
|
|
cwd=str(repo_path),
|
|
)
|
|
await process.wait()
|
|
|
|
|
|
async def git_log(repo_path: str) -> str:
|
|
cmd = [
|
|
"git",
|
|
"log",
|
|
"--since=1 week ago",
|
|
"--pretty=format:%h - %an, %ar : %s",
|
|
"--stat",
|
|
"--patch",
|
|
]
|
|
process = await asyncio.create_subprocess_exec(
|
|
*cmd,
|
|
cwd=repo_path,
|
|
stdout=asyncio.subprocess.PIPE,
|
|
stderr=asyncio.subprocess.PIPE,
|
|
)
|
|
stdout, stderr = await process.communicate()
|
|
|
|
if process.returncode != 0:
|
|
raise Exception(
|
|
f"Command '{' '.join(cmd)}' failed with exit code {process.returncode}"
|
|
)
|
|
|
|
return stdout.decode()
|
|
|
|
|
|
async def changelog_bot(
|
|
client: AsyncClient,
|
|
http: aiohttp.ClientSession,
|
|
matrix: MatrixData,
|
|
gitea: GiteaData,
|
|
data_dir: Path,
|
|
) -> None:
|
|
# If you made a new room and haven't joined as that user, you can use
|
|
room: JoinResponse = await client.join(matrix.room)
|
|
|
|
if not room.transport_response.ok:
|
|
log.error("This can happen if the room doesn't exist or the bot isn't invited")
|
|
raise Exception(f"Failed to join room {room}")
|
|
|
|
repo_path = data_dir / gitea.repo
|
|
|
|
if not repo_path.exists():
|
|
cmd = [
|
|
"git",
|
|
"clone",
|
|
f"{gitea.url}/{gitea.owner}/{gitea.repo}.git",
|
|
gitea.repo,
|
|
]
|
|
subprocess.run(cmd, cwd=data_dir, check=True)
|
|
|
|
# git pull
|
|
await git_pull(repo_path)
|
|
|
|
# git log
|
|
diff = await git_log(repo_path)
|
|
|
|
system_prompt = """
|
|
Generate a concise changelog for the past week,
|
|
focusing only on new features and summarizing bug fixes into a single entry.
|
|
Ensure the following:
|
|
|
|
- Deduplicate entries
|
|
- Discard uninteresting changes
|
|
- Keep the summary as brief as possible
|
|
- Use present tense
|
|
The changelog is as follows:
|
|
---
|
|
"""
|
|
|
|
jsonl_path = data_dir / "changelog.jsonl"
|
|
|
|
# Step 1: Create the JSONL file
|
|
await create_jsonl_file(
|
|
user_prompt=diff, system_prompt=system_prompt, jsonl_path=jsonl_path
|
|
)
|
|
|
|
# Step 2: Upload the JSONL file and process it
|
|
results = await upload_and_process_file(session=http, jsonl_path=jsonl_path)
|
|
result_file = write_file_with_date_prefix(json.dumps(results, indent=4), data_dir, "result")
|
|
|
|
log.info(f"LLM result written to: {result_file}")
|
|
|
|
# Join all changelogs with a separator (e.g., two newlines)
|
|
all_changelogs = []
|
|
for result in results:
|
|
choices = result["response"]["body"]["choices"]
|
|
changelog = "\n".join(choice["message"]["content"] for choice in choices)
|
|
all_changelogs.append(changelog)
|
|
full_changelog = "\n\n".join(all_changelogs)
|
|
|
|
|
|
await send_message(client, room, full_changelog)
|