0
This commit is contained in:
33
api.py
33
api.py
@@ -53,6 +53,7 @@ class ClockifyAPI(ClockifyConfig):
|
|||||||
task_id, task_title = tag.title.split(" - ")
|
task_id, task_title = tag.title.split(" - ")
|
||||||
result.append(
|
result.append(
|
||||||
Activity(
|
Activity(
|
||||||
|
id=activity["id"],
|
||||||
task_id=task_id,
|
task_id=task_id,
|
||||||
task_title=task_title,
|
task_title=task_title,
|
||||||
description=activity["description"],
|
description=activity["description"],
|
||||||
@@ -77,6 +78,25 @@ class ClockifyAPI(ClockifyConfig):
|
|||||||
title=tag["name"]
|
title=tag["name"]
|
||||||
) for tag in tags]
|
) for tag in tags]
|
||||||
|
|
||||||
|
def mark_tracked(self, activities: list[Activity]):
|
||||||
|
for activity in activities:
|
||||||
|
try:
|
||||||
|
resp = requests.put(self.base_url + self.update_time_entry.format(
|
||||||
|
workspace_id=WORKSPACE_ID,
|
||||||
|
id=activity.id
|
||||||
|
), data={
|
||||||
|
"description": "*" + activity.description
|
||||||
|
})
|
||||||
|
if resp.ok:
|
||||||
|
logging.debug(activity, "помечена как затреканная")
|
||||||
|
else:
|
||||||
|
logging.error(activity, "не помечена как затреканная")
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(e)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _check_token(self, token: str) -> str:
|
def _check_token(self, token: str) -> str:
|
||||||
resp = requests.get(self.base_url + self.config.user_url, headers={"X-API-KEY": token})
|
resp = requests.get(self.base_url + self.config.user_url, headers={"X-API-KEY": token})
|
||||||
if not resp.ok:
|
if not resp.ok:
|
||||||
@@ -91,11 +111,11 @@ class RedmineAPI(RedmineConfig):
|
|||||||
def __init__(self, token):
|
def __init__(self, token):
|
||||||
self.token = self._check_token(token)
|
self.token = self._check_token(token)
|
||||||
|
|
||||||
def track_activities(self, activities: list[Activity]):
|
def track_activities(self, activities: list[Activity]) -> list[Activity]:
|
||||||
if len(activities) == 0:
|
if len(activities) == 0:
|
||||||
logging.info("Нет задач для занесения трудочасов")
|
logging.info("Нет задач для занесения трудочасов")
|
||||||
return
|
return
|
||||||
tracked = 0
|
tracked = []
|
||||||
for activity in tqdm(activities, desc="Занесение трудочасов"):
|
for activity in tqdm(activities, desc="Занесение трудочасов"):
|
||||||
if not activity.is_tracked:
|
if not activity.is_tracked:
|
||||||
try:
|
try:
|
||||||
@@ -114,7 +134,7 @@ class RedmineAPI(RedmineConfig):
|
|||||||
)
|
)
|
||||||
if resp.ok:
|
if resp.ok:
|
||||||
activity.is_tracked = True
|
activity.is_tracked = True
|
||||||
tracked += 1
|
tracked.append(activity)
|
||||||
logging.debug(activity)
|
logging.debug(activity)
|
||||||
else:
|
else:
|
||||||
logging.error(activity, "Не была затрекана")
|
logging.error(activity, "Не была затрекана")
|
||||||
@@ -122,8 +142,11 @@ class RedmineAPI(RedmineConfig):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(e)
|
logging.error(e)
|
||||||
continue
|
continue
|
||||||
if len(activities) == tracked:
|
if len(activities) == len(tracked):
|
||||||
logging.info(f"Все задачи были успешно занесены в Redmine: {tracked}")
|
logging.info("Все задачи были успешно занесены в Redmine")
|
||||||
|
else:
|
||||||
|
logging.info(f"Не все задачи были занесены в Redmine. Занесено {len(tracked)}")
|
||||||
|
return tracked
|
||||||
|
|
||||||
|
|
||||||
def _check_token(self, token):
|
def _check_token(self, token):
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ from datetime import datetime
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Activity:
|
class Activity:
|
||||||
|
id: str
|
||||||
task_id: int
|
task_id: int
|
||||||
task_title: str
|
task_title: str
|
||||||
description: str
|
description: str
|
||||||
@@ -15,7 +16,7 @@ class Activity:
|
|||||||
return self.description.startswith("*")
|
return self.description.startswith("*")
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f'{self.date}: {self.description.strip("*")} для задачи "{self.task_title}"' + (" - ЗАТРЕКАНА" if self.is_tracked else "")
|
return f'{self.date}: {self.description.strip("*")} для задачи "{self.task_title}"'
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|||||||
@@ -50,5 +50,9 @@ class ClockifyConfig:
|
|||||||
def datetime_format(self):
|
def datetime_format(self):
|
||||||
return "%Y-%m-%dT%H:%M:%SZ"
|
return "%Y-%m-%dT%H:%M:%SZ"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def update_time_entry(self):
|
||||||
|
return "/workspaces/{workspaceId}/time-entries/{id}"
|
||||||
|
|
||||||
|
|
||||||
config = Config()
|
config = Config()
|
||||||
|
|||||||
7
main.py
7
main.py
@@ -7,13 +7,16 @@ from utils import today_start, today_end
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
if False:
|
|
||||||
clock = ClockifyAPI(config.CLOCKIFY_TOKEN)
|
clock = ClockifyAPI(config.CLOCKIFY_TOKEN)
|
||||||
red = RedmineAPI(config.REDMINE_TOKEN)
|
red = RedmineAPI(config.REDMINE_TOKEN)
|
||||||
red.track_activities(clock.get_activities(
|
if False:
|
||||||
|
tracked_activities = red.track_activities(clock.get_activities(
|
||||||
start=today_start(),
|
start=today_start(),
|
||||||
end=today_end()
|
end=today_end()
|
||||||
))
|
))
|
||||||
|
clock.mark_tracked(tracked_activities)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
Reference in New Issue
Block a user