-
-
Notifications
You must be signed in to change notification settings - Fork 116
Expand file tree
/
Copy pathget_contributor_user_info.py
More file actions
150 lines (131 loc) · 5.48 KB
/
get_contributor_user_info.py
File metadata and controls
150 lines (131 loc) · 5.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
import os
import sys
import requests
from pathlib import Path
from time import sleep
from PIL import Image
from io import BytesIO
from typing import Optional
import time
import urllib.parse
# Tuple of GitHub login ID to string resource ID
# Use following command to get a rough idea who should be on this list:
# git shortlog -n -s -- ':!app/src/main/res/values*/strings.xml' ':!fastlane/metadata/android/' ':!readme*.md'
GITHUB_USERS = [
("nift4", "contributors_nift4"),
("123Duo3", "contributors_123duo3"),
("AkaneTan", "contributors_akanetan"),
("mikooomich", "contributors_developer"),
("imjyotiraditya", "contributors_developer"),
("WSTxda", "contributors_wstxda"),
("pxeemo", "contributors_pxeemo"),
("saladnoober", "contributors_saladnoober"),
("Lambada10", "contributors_lambada10"),
("lightsummer233", "contributors_developer"),
("nicholaswww", "contributors_code_contributions"),
("Yuyuko1024", "contributors_yuyuko1024"),
("ghhccghk", "contributors_ghhccghk"),
("lucaxvi", "contributors_code_contributions"),
("tungnk123", "contributors_code_contributions"),
("ne-kle", "contributors_code_contributions"),
("topazrn", "contributors_code_contributions"),
("strongville", "contributors_code_contributions"),
("SurFace81", "contributors_code_contributions"),
("bggRGjQaUbCoE", "contributors_code_contributions"),
("VishnuSanal", "contributors_code_contributions"),
("HotarunIchijou", "contributors_code_contributions"),
("someone5678", "contributors_code_contributions"),
("PalanixYT", "contributors_code_contributions"),
("N3Shemmy3", "contributors_code_contributions"),
("SharnavM", "contributors_code_contributions"),
]
# TODO: delete old webp files so that webp file is removed if someone is removed from credits
DRAWABLE_DIR = "app/src/main/res/drawable"
OUTPUT_KT = "app/src/main/java/org/akanework/gramophone/logic/utils/data/Contributors.kt"
API_BASE = "https://api.github.com/users/"
WEBLATE_CREDITS = "https://hosted.weblate.org/api/projects/gramophone/credits/?start=1970-01-01T00:00:00Z&end=2099-01-01T00:00:00Z"
HEADERS = {
"Accept": "application/vnd.github+json",
}
WEBLATE_HEADERS = {
"Accept": "application/json",
}
try:
with open("fastlane/creds.txt", "r", encoding="utf-8") as f:
HEADERS["Authorization"] = "Bearer " + f.read().strip()
except Exception as e:
print("Not using auth, may be subject to rate limits")
try:
with open("fastlane/weblate.txt", "r", encoding="utf-8") as f:
WEBLATE_HEADERS["Authorization"] = "Bearer " + f.read().strip()
except Exception as e:
print("Missing weblate API key")
sys.exit(1)
def sanitize_login(login: str) -> str:
return ''.join(c if c.isalnum() else '_' for c in login.lower())
def fetch_user_data(login: str) -> Optional[dict]:
url = f"{API_BASE}{login}"
try:
response = requests.get(url, headers=HEADERS, timeout=10)
response.raise_for_status()
return response.json()
except Exception as e:
print(f"❌ get users error {login}: {e}")
return None
def fetch_translation_credits() -> Optional[dict]:
try:
response = requests.get(WEBLATE_CREDITS, headers=WEBLATE_HEADERS, timeout=10)
response.raise_for_status()
return response.json()
except Exception as e:
print(f"❌ get credits error: {e}")
return None
def download_and_save_avatar(url: str, filename: str):
response = requests.get(url, timeout=10)
response.raise_for_status()
img = Image.open(BytesIO(response.content)).convert("RGBA")
img.thumbnail((128, 128))
os.makedirs(DRAWABLE_DIR, exist_ok=True)
filepath = os.path.join(DRAWABLE_DIR, f"{filename}.webp")
img.save(filepath, format="WebP", quality=50, method=6)
print(f"✅ download ok: {filepath}")
def main():
result = """// ===== DO NOT EDIT, CHANGES WILL BE OVERWRITTEN =====
// automatically generated by get_contributor_user_info.py
package org.akanework.gramophone.logic.utils.data
import android.net.Uri
import org.akanework.gramophone.R
object Contributors {
private fun decode(text: String?) = text?.let { Uri.decode(it) }
val LIST = listOf("""
for user in GITHUB_USERS:
login = user[0]
print(f"📦 Processing users: {login}")
user_data = fetch_user_data(login)
if not user_data:
return
filename = f"contributor_{sanitize_login(login)}"
avatar_url = user_data.get("avatar_url", "")
name = ("\"" + urllib.parse.quote(user_data["name"]) + "\"") if ("name" in user_data and user_data["name"]) else "null"
download_and_save_avatar(avatar_url, filename)
result += f"\n GitHubUser(login = \"{login}\", name = decode({name}), avatar = R.drawable.{filename}, contributed = R.string.{user[1]}),"
result += "\n )\n"
print("📦 Fetching credits from Weblate")
credits = fetch_translation_credits()
if not credits:
return
names = set()
for language in credits:
for users in language.values():
for user in users:
names.add(user["full_name"])
result += " val TRANSLATORS = listOf("
names = sorted(names)
for name in names:
result += "\n decode(\"" + urllib.parse.quote(name) + "\"),"
result += "\n )\n}\n"
with open(OUTPUT_KT, "w", encoding="utf-8") as f:
f.write(result)
print(f"\n✅ All user processing is complete and results have been saved to {OUTPUT_KT}")
if __name__ == "__main__":
main()