Files
wakapi-readme-stats/sources/main.py
2023-02-26 08:01:04 +01:00

206 lines
8.1 KiB
Python

"""
Readme Development Metrics With waka time progress
"""
from asyncio import run
from datetime import datetime
from urllib.parse import quote
from humanize import intword, naturalsize, intcomma
from manager_download import init_download_manager, DownloadManager as DM
from manager_environment import EnvironmentManager as EM
from manager_github import init_github_manager, GitHubManager as GHM
from manager_localization import init_localization_manager, LocalizationManager as LM
from manager_debug import init_debug_manager, DebugManager as DBM
from graphics_chart_drawer import create_loc_graph, GRAPH_PATH
from yearly_commit_calculator import calculate_yearly_commit_data
from graphics_list_formatter import make_list, make_commit_day_time_list, make_language_per_repo_list
async def get_waka_time_stats() -> str:
"""
Collects user info from wakatime.
Info includes most common commit time, timezone, language, editors, projects and OSs.
:returns: String representation of the info.
"""
DBM.i("Adding short WakaTime stats...")
stats = str()
data = await DM.get_remote_json("waka_latest")
if EM.SHOW_COMMIT:
DBM.i("Adding user commit day time info...")
stats += f"{await make_commit_day_time_list(data['data']['timezone'])}\n\n"
if EM.SHOW_TIMEZONE or EM.SHOW_LANGUAGE or EM.SHOW_EDITORS or EM.SHOW_PROJECTS or EM.SHOW_OS:
no_activity = LM.t("No Activity Tracked This Week")
stats += f"📊 **{LM.t('This Week I Spend My Time On')}** \n\n```text\n"
if EM.SHOW_TIMEZONE:
DBM.i("Adding user timezone info...")
time_zone = data["data"]["timezone"]
stats += f"🕑︎ {LM.t('Timezone')}: {time_zone}\n\n"
if EM.SHOW_LANGUAGE:
DBM.i("Adding user top languages info...")
lang_list = no_activity if len(data["data"]["languages"]) == 0 else make_list(data["data"]["languages"])
stats += f"💬 {LM.t('Languages')}: \n{lang_list}\n\n"
if EM.SHOW_EDITORS:
DBM.i("Adding user editors info...")
edit_list = no_activity if len(data["data"]["editors"]) == 0 else make_list(data["data"]["editors"])
stats += f"🔥 {LM.t('Editors')}: \n{edit_list}\n\n"
if EM.SHOW_PROJECTS:
DBM.i("Adding user projects info...")
project_list = no_activity if len(data["data"]["projects"]) == 0 else make_list(data["data"]["projects"])
stats += f"🐱‍💻 {LM.t('Projects')}: \n{project_list}\n\n"
if EM.SHOW_OS:
DBM.i("Adding user operating systems info...")
os_list = no_activity if len(data["data"]["operating_systems"]) == 0 else make_list(data["data"]["operating_systems"])
stats += f"💻 {LM.t('operating system')}: \n{os_list}\n\n"
stats = f"{stats[:-1]}```\n\n"
DBM.g("WakaTime stats added!")
return stats
async def get_short_github_info() -> str:
"""
Collects user info from GitHub public profile.
The stats include: disk usage, contributions number, whether the user has opted to hire, public and private repositories number.
:returns: String representation of the info.
"""
DBM.i("Adding short GitHub info...")
stats = f"**🐱 {LM.t('My GitHub Data')}** \n\n"
DBM.i("Adding user disk usage info...")
if GHM.USER.disk_usage is None:
disk_usage = LM.t("Used in GitHub's Storage") % "?"
DBM.p("Please add new github personal access token with user permission!")
else:
disk_usage = LM.t("Used in GitHub's Storage") % naturalsize(GHM.USER.disk_usage)
stats += f"> 📦 {disk_usage} \n > \n"
data = await DM.get_remote_json("github_stats")
DBM.i("Adding contributions info...")
if len(data["years"]) > 0:
contributions = LM.t("Contributions in the year") % (intcomma(data["years"][0]["total"]), data["years"][0]["year"])
stats += f"> 🏆 {contributions}\n > \n"
else:
DBM.p("GitHub contributions data unavailable!")
DBM.i("Adding opted for hire info...")
opted_to_hire = GHM.USER.hireable
if opted_to_hire:
stats += f"> 💼 {LM.t('Opted to Hire')}\n > \n"
else:
stats += f"> 🚫 {LM.t('Not Opted to Hire')}\n > \n"
DBM.i("Adding public repositories info...")
public_repo = GHM.USER.public_repos
if public_repo != 1:
stats += f"> 📜 {LM.t('public repositories') % public_repo} \n > \n"
else:
stats += f"> 📜 {LM.t('public repository') % public_repo} \n > \n"
DBM.i("Adding private repositories info...")
private_repo = GHM.USER.owned_private_repos if GHM.USER.owned_private_repos is not None else 0
if public_repo != 1:
stats += f"> 🔑 {LM.t('private repositories') % private_repo} \n > \n"
else:
stats += f"> 🔑 {LM.t('private repository') % private_repo} \n > \n"
DBM.g("Short GitHub info added!")
return stats
async def get_stats() -> str:
"""
Creates new README.md content from all the acquired statistics from all places.
The readme includes data from wakatime, contributed lines of code number, GitHub profile info and last updated date.
:returns: String representation of README.md contents.
"""
DBM.i("Collecting stats for README...")
stats = str()
repositories = await DM.get_remote_graphql("user_repository_list", username=GHM.USER.login, id=GHM.USER.node_id)
if EM.SHOW_LINES_OF_CODE or EM.SHOW_LOC_CHART:
yearly_data = await calculate_yearly_commit_data(repositories)
else:
yearly_data = (None, dict())
DBM.w("User yearly data not needed, skipped.")
if EM.SHOW_TOTAL_CODE_TIME:
DBM.i("Adding total code time info...")
data = await DM.get_remote_json("waka_all")
stats += f"![Code Time](http://img.shields.io/badge/{quote('Code Time')}-{quote(str(data['data']['text']))}-blue)\n\n"
if EM.SHOW_PROFILE_VIEWS:
DBM.i("Adding profile views info...")
data = GHM.REPO.get_views_traffic(per="week")
stats += f"![Profile Views](http://img.shields.io/badge/{quote(LM.t('Profile Views'))}-{data['count']}-blue)\n\n"
if EM.SHOW_LINES_OF_CODE:
DBM.i("Adding lines of code info...")
total_loc = sum([yearly_data[y][q][d] for y in yearly_data.keys() for q in yearly_data[y].keys() for d in yearly_data[y][q].keys()])
data = f"{intword(total_loc)} {LM.t('Lines of code')}"
stats += f"![Lines of code](https://img.shields.io/badge/{quote(LM.t('From Hello World I have written'))}-{quote(data)}-blue)\n\n"
if EM.SHOW_SHORT_INFO:
stats += await get_short_github_info()
stats += await get_waka_time_stats()
if EM.SHOW_LANGUAGE_PER_REPO:
DBM.i("Adding language per repository info...")
stats += f"{make_language_per_repo_list(repositories)}\n\n"
if EM.SHOW_LOC_CHART:
await create_loc_graph(yearly_data, GRAPH_PATH)
GHM.update_chart(GRAPH_PATH)
chart_path = f"{GHM.USER.login}/{GHM.USER.login}/{GHM.branch()}/{GRAPH_PATH}"
stats += f"**{LM.t('Timeline')}**\n\n![Lines of Code chart](https://raw.githubusercontent.com/{chart_path})\n\n"
if EM.SHOW_UPDATED_DATE:
DBM.i("Adding last updated time...")
stats += f"\n Last Updated on {datetime.now().strftime(EM.UPDATED_DATE_FORMAT)} UTC"
DBM.g("Stats for README collected!")
return stats
async def main():
"""
Application main function.
Initializes all managers, collects user info and updates README.md if necessary.
"""
init_github_manager()
await init_download_manager()
init_localization_manager()
DBM.i("Managers initialized.")
stats = await get_stats()
if not EM.DEBUG_RUN:
if GHM.update_readme(stats):
DBM.g("Readme updated!")
else:
GHM.push_to_pr(stats)
DBM.g("Debug run, readme not updated. Check the latest comment for the generated stats.")
await DM.close_remote_resources()
if __name__ == "__main__":
init_debug_manager()
start_time = datetime.now()
DBM.g("Program execution started at $date.", date=start_time)
run(main())
end_time = datetime.now()
DBM.g("Program execution finished at $date.", date=end_time)
DBM.p("Program finished in $time.", time=end_time - start_time)