Last active
March 22, 2023 10:45
-
-
Save yihong0618/01ec1c28e9e8dcfc59906d3a869314ca to your computer and use it in GitHub Desktop.
专注森林.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import argparse | |
import json | |
from collections import Counter | |
from datetime import datetime | |
import pendulum | |
import requests | |
from rich import print | |
FOREST_URL_HEAD = "https://forest-china.upwardsware.com" | |
FOREST_LOGIN_URL = FOREST_URL_HEAD + "/api/v1/sessions" | |
FOREST_CLAENDAR_URL = ( | |
FOREST_URL_HEAD | |
+ "/api/v1/plants/updated_plants?update_since={date}&seekruid={user_id}" | |
) | |
FOREST_TAG_URL = FOREST_URL_HEAD + "/api/v1/tags?seekruid={user_id}" | |
FOREST_SUMMARY_HEAD = "| Tag | Times | \n | ---- | ---- | \n" | |
FOREST_SUMMARY_STAT_TEMPLATE = "| {tag} | {times} |\n" | |
TIMEZONE = "Asia/Shanghai" | |
class Forst: | |
def __init__(self, email, password): | |
self.email = email | |
self.password = password | |
self.s = requests.Session() | |
self.year = datetime.now().year | |
self.user_id = None | |
self.plants = [] | |
self.log_days = [] | |
self.success_plants_count = 0 | |
self.is_login = False | |
def login(self): | |
data = {"session": {"email": self.email, "password": self.password}} | |
headers = {"Content-Type": "application/json"} | |
r = self.s.post(FOREST_LOGIN_URL, headers=headers, data=json.dumps(data)) | |
if not r.ok: | |
raise Exception(f"Someting is wrong to login -- {r.text}") | |
self.user_id = r.json()["user_id"] | |
self.is_login = True | |
def make_plants_data(self): | |
if not self.is_login: | |
self.login() | |
date = str(self.year) + "-01-01" | |
r = self.s.get(FOREST_CLAENDAR_URL.format(date=date, user_id=self.user_id)) | |
if not r.ok: | |
raise Exception(f"Someting is wrong to get data-- {r.text}") | |
self.plants = r.json()["plants"] | |
# only count success trees | |
self.plants = [i for i in self.plants if i["is_success"]] | |
def _get_my_tags(self): | |
r = self.s.get(FOREST_TAG_URL.format(user_id=self.user_id)) | |
if not r.ok: | |
raise Exception("Can not get tags") | |
tag_list = r.json().get("tags", []) | |
tag_dict = {} | |
for t in tag_list: | |
tag_dict[t["tag_id"]] = t["title"] | |
return tag_dict | |
# make forst tag like "代码" "日语" as key | |
def _make_forest_dict(self, plants): | |
if not self.plants: | |
self.make_plants_data() | |
tags_dict = self._get_my_tags() | |
d = Counter() | |
for p in plants: | |
d[tags_dict[p.get("tag")]] += 1 | |
return d | |
@staticmethod | |
def _make_tag_summary_str(tag_summary_dict, unit): | |
s = FOREST_SUMMARY_HEAD | |
for k, v in tag_summary_dict.most_common(): | |
s += FOREST_SUMMARY_STAT_TEMPLATE.format(tag=k, times=str(v) + f" {unit}") | |
return s | |
def make_table_body(self, plants, date_str=""): | |
unit = "个" | |
body = "" | |
tag_summary_dict = self._make_forest_dict(plants) | |
if date_str: | |
body = ( | |
f"{date_str} 的 Forst 番茄时间汇总" | |
+ "\r\n" | |
+ self._make_tag_summary_str(tag_summary_dict, unit) | |
) | |
# if no date str is the issue body --> sunmmary | |
else: | |
body = body + "\r\n" + self._make_tag_summary_str(tag_summary_dict, unit) | |
return body | |
def make_year_stats_table(self): | |
self.make_plants_data() | |
plants = self.plants | |
body = self.make_table_body(plants) | |
print(body) | |
def make_plants_body(self, day): | |
""" | |
if there no day we do not need to filter | |
TODO refactor here | |
""" | |
if not day: | |
return self.make_table_body(self.plants) | |
plants = [ | |
i | |
for i in self.plants | |
if pendulum.parse(i["start_time"]).in_timezone(TIMEZONE).to_date_string() | |
== day.to_date_string() | |
] | |
if not plants: | |
# if not plants we return empty string | |
return f"{day.to_date_string()} 的 Forst " | |
return self.make_table_body(plants, day.to_date_string()) | |
def _init_plants(self): | |
""" | |
TODO | |
only support two days now? | |
if I want to make the year repo to template | |
I must support this | |
""" | |
pass | |
def make_daily_table(self): | |
today = pendulum.now(TIMEZONE) | |
yesterday = pendulum.now(TIMEZONE).subtract(days=1) | |
yesterday_body = self.make_plants_body(yesterday) | |
today_body = self.make_plants_body(today) | |
def make_forst_daily(self): | |
end_date = pendulum.now(TIMEZONE) | |
start_date = end_date.start_of("year") | |
log_days = set( | |
[ | |
pendulum.parse(i["start_time"]).in_timezone(TIMEZONE).to_date_string() | |
for i in self.plants | |
] | |
) | |
self.log_days = sorted(list(log_days)) | |
is_today_check = False | |
if end_date.to_date_string() in self.log_days: | |
is_today_check = True | |
periods = list(pendulum.period(start_date, end_date.subtract(days=1))) | |
periods.sort(reverse=True) | |
# if today id done | |
streak = 0 | |
if end_date.to_date_string() in self.log_days: | |
streak += 1 | |
for p in periods: | |
if p.to_date_string() not in self.log_days: | |
break | |
streak += 1 | |
# total plants, streak, is_today_check | |
return len(self.plants), streak, is_today_check | |
if __name__ == "__main__": | |
parser = argparse.ArgumentParser() | |
parser.add_argument("email", help="email") | |
parser.add_argument("password", help="password") | |
options = parser.parse_args() | |
f = Forst(options.email, options.password) | |
f.login() | |
f.make_daily_table() | |
f.make_year_stats_table() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment