이번에도 꽤나 어려웠다.
이번 목표는 깃 허브의 백준 문제가 저장된 repo에서 가장 최근에 커밋된 파일을 따오는 것이었다.
여러 번 시행착오를 반복한 이유는 Git에 commit_date가 저장되지 않은 파일들이 존재했기 때문이다.
처음에 각 파일들을 읽어들여 commit_date를 비교하여 최신의 것을 가져오려했다.
import os
import requests
import base64
def decode_base64(encoded_content):
try:
decoded_bytes = base64.b64decode(encoded_content)
decoded_str = decoded_bytes.decode('utf-8')
return decoded_str
except Exception as e:
print(f'Failed to decode Base64: {str(e)}')
return None
def get_latest_commit_files(owner, repo, token):
# GitHub API 엔드포인트
api_url = f'https://api.github.com/repos/{owner}/{repo}/commits?per_page=1'
# API 호출
response = requests.get(api_url, headers={'Authorization': f'token {token}'})
# 응답 확인
if response.status_code == 200:
# 응답에서 최신 커밋의 SHA 가져오기
latest_commit_sha = response.json()[0]['sha']
# 다시 API 호출하여 해당 커밋의 파일 목록 가져오기
api_url = f'https://api.github.com/repos/{owner}/{repo}/git/trees/{latest_commit_sha}?recursive=1'
response = requests.get(api_url, headers={'Authorization': f'token {token}'})
# 응답 확인
if response.status_code == 200:
# 응답에서 'tree' 키에 해당하는 값 가져오기
tree_data = response.json().get('tree')
if tree_data is not None and isinstance(tree_data, list):
# 마크다운 파일(.md)과 코드 파일(.cc) 중에서 최신 커밋의 것을 선택
selected_files = [item['path'] for item in tree_data if item['type'] == 'blob' and
(item['path'].endswith('.md') or item['path'].endswith('.cc'))]
# 최신 파일 선택
latest_file = max(selected_files, key=lambda x: tree_data[selected_files.index(x)].get('last_modified', 0))
# 최신 파일의 내용 가져오기
file_api_url = f'https://api.github.com/repos/{owner}/{repo}/contents/{latest_file}?ref={latest_commit_sha}'
file_response = requests.get(file_api_url, headers={'Authorization': f'token {token}'})
if file_response.status_code == 200:
file_data = file_response.json()
file_content = decode_base64(file_data['content'])
return {latest_file: file_content}
else:
print(f'Failed to fetch file content. Status code: {file_response.status_code}')
else:
print('Invalid response format.')
else:
print(f'Failed to fetch file list. Status code: {response.status_code}')
else:
print(f'Failed to fetch latest commit. Status code: {response.status_code}')
# GitHub repository 정보
owner = 'git546'
repo = 'BOJ'
token = '비밀'
# 함수 호출
file_content = get_latest_commit_files(owner, repo, token)
# 출력
for file, content in file_content.items():
print(f'File: {file}')
print(content)
print('\n' + '-'*50 + '\n')
하지만 해당하는 date가 없었기 때문에 commit_date는 제대로 갱신되지 않았던 것이다.
그래서 출력으로
repo 최상단의 repo 생성시 생긴 파일이 최신 커밋으로 출력되었다.
이후 방향을 바꾸어 파일들에서 date를 읽어내는 대신 commit 기록을 바탕으로 하기로 하였다.
def get_repository_latest_commit_sha(owner, repo, token):
api_url = f'https://api.github.com/repos/{owner}/{repo}/commits'
headers = {'Authorization': f'token {token}'}
response = requests.get(api_url, headers=headers)
if response.status_code == 200:
commits = response.json()
latest_commit_sha = commits[0]['sha'] if commits else None
return latest_commit_sha
else:
print(f'Failed to fetch repository commits. Status code: {response.status_code}')
return None
이게 해당 함수이다. 지정된 경로에서 sha 중 가장 최근의 것을 return 하며 없는 경우 에러 코드를 반환한다.
def get_commit_files(owner, repo, commit_sha, token):
api_url = f'https://api.github.com/repos/{owner}/{repo}/commits/{commit_sha}'
response = requests.get(api_url, headers={'Authorization': f'token {token}'})
if response.status_code == 200:
commit_info = response.json()
files_changed = commit_info.get('files', [])
MD_content = None
CC_content = None
for file_change in files_changed:
file_status = file_change['status'] # 추가('added'), 수정('modified'), 삭제('removed')
file_path = file_change['filename'] # 파일 경로
if file_path.endswith('.md') and file_status == 'added':
MD_content = get_file_content(owner, repo, file_path, token)
elif file_path.endswith('.cc') and file_status == 'added':
CC_content = get_file_content(owner, repo, file_path, token)
return MD_content, CC_content
else:
print(f'Failed to fetch commit information. Status code: {response.status_code}')
return None, None
이를 활용하여 해당 커밋된 날짜에 커밋된 파일을 content에 담아 반환하는 함수를 만들었다. commit 상태가 추가에 해당하는 경우에만 경로에 따라 해당 파일을 지정된 변수에 담아 반환해 준다.
위 함수 중간에 사용된 get_file_content는 지정된 path의 파일을 가져와 반환하는 함수로
def get_file_content(owner, repo, file_path, token):
api_url = f'https://api.github.com/repos/{owner}/{repo}/contents/{file_path}'
headers = {'Authorization': f'token {token}'}
response = requests.get(api_url, headers=headers)
if response.status_code == 200:
file_data = response.json()
file_content = base64.b64decode(file_data['content']).decode('utf-8')
return file_content
else:
print(f'파일 내용을 불러오지 못했습니다. 상태 코드: {response.status_code}')
return None
의 구조로 되어있다.
이를 다음과 같이 활용하며 최신 커밋된 파일들의 내용을 출력해 확인할 수 있다.
# 함수 호출
latest_commit_sha = get_repository_latest_commit_sha(owner, repo, token)
if latest_commit_sha:
print(f'Latest commit SHA: {latest_commit_sha}')
MD_content, CC_content = get_commit_files(owner, repo, latest_commit_sha, token)
# 출력 또는 다른 작업 수행
if MD_content is not None:
print(f'Markdown 파일 내용:\n{MD_content}')
else:
print('Markdown 파일 내용을 불러오지 못했습니다.')
if CC_content is not None:
print(f'C++ 파일 내용:\n{CC_content}')
else:
print('C++ 파일 내용을 불러오지 못했습니다.')
else:
print('Failed to get the latest commit SHA.')
Markdown 파일 내용:
# [Silver IV] 순서쌍의 곱의 합 - 13900
[문제 링크](https://www.acmicpc.net/problem/13900)
### 성능 요약
메모리: 3464 KB, 시간: 44 ms
### 분류
수학, 누적 합
### 제출 일자
2023년 12월 19일 01:26:58
### 문제 설명
<p>N개의 정수 중 서로 다른 위치의 두 수를 뽑는 모든 경우의 두 수의 곱의 합을 구하라.</p>
<p>예를 들어 N = 3이고 주어진 정수가 2, 3, 4일 때, 두 수를 뽑는 모든 경우는 (2, 3), (2, 4), (3, 4)이며 이때 각각의 곱은 6, 8, 12이다. 따라서 총합은 26이다.</p>
### 입력
<p>첫 번째 줄에는 입력 받을 정수의 개수 N(<strong>2 ≤ N ≤ 100,000</strong>)</p>
<p>두 번째 줄에는 N 개의 정수가 주어진다. 이때 입력 받는 정수들의 범위는 <strong>0이상 10,000 이하이다.</strong></p>
### 출력
<p>모든 경우의 곱의 합을 출력한다.</p>
C++ 파일 내용:
#include <iostream>
#define fastio ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
using namespace std;
int main() {
int N;
cin >> N;
long arr[100000];
for (int i = 0; i < N; ++i) {
cin >> arr[i];
}
long answer = 0;
long psum[100000];
psum[0] = arr[0];
for (int i = 1; i < N; ++i) {
psum[i] = psum[i - 1] + arr[i];
}
for (int i = 0; i < N - 1; ++i) {
answer += arr[i] * (psum[N - 1] - psum[i]);
}
cout << answer;
}
그리고 출력해본 결과 가장 최신의 파일이 불러와진 것을 확인할 수 있었다.
'개발 기록 > 자동 포스팅 프로그램' 카테고리의 다른 글
인터페이스 설정 (0) | 2023.12.26 |
---|---|
몇 가지 기능 갱신 (0) | 2023.12.22 |
posting content 파트 완성!! (1) | 2023.12.18 |
chat gpt를 이용한 코드 작성 도움 및 경과 (1) | 2023.12.14 |
md 파일 포스팅 현황 (0) | 2023.12.13 |