1919
2020from api .v1 .auth .main import require_auth , send_otp_code # type: ignore
2121from db import get_db
22- from lib .hackatime import get_projects
22+ from lib .hackatime import get_account , get_projects
2323from models .user import User
2424
2525router = APIRouter ()
@@ -217,7 +217,7 @@ async def recalculate_hackatime_time(
217217 try :
218218 user_projects = get_projects (user .hackatime_id , list (all_hackatime_projects ))
219219 except Exception as e : # type: ignore # pylint: disable=broad-exception-caught
220- error ("Error fetching Hackatime projects:" , e )
220+ error ("Error fetching Hackatime projects:" , exc_info = e )
221221 raise HTTPException (
222222 status_code = 500 , detail = "Error fetching Hackatime projects"
223223 ) from e
@@ -242,15 +242,65 @@ async def recalculate_hackatime_time(
242242 return Response (status_code = 204 )
243243 except Exception as e : # type: ignore # pylint: disable=broad-exception-caught
244244 await session .rollback ()
245- error ("Error updating Hackatime data:" , e )
245+ error ("Error updating Hackatime data:" , exc_info = e )
246246 raise HTTPException (
247247 status_code = 500 , detail = "Error updating Hackatime data"
248248 ) from e
249249
250+ @router .get ("/retry_hackatime_link" )
251+ @require_auth
252+ async def retry_hackatime_link (
253+ request : Request ,
254+ session : AsyncSession = Depends (get_db ),
255+ ):
256+ """Retry linking Hackatime account for a user"""
257+ user_email = request .state .user ["sub" ]
250258
251- # disabled for 30 days, no login -> delete
259+ user_raw = await session .execute (
260+ sqlalchemy .select (User ).where (User .email == user_email )
261+ )
252262
263+ user = user_raw .scalar_one_or_none ()
253264
265+ if user is None :
266+ raise HTTPException (
267+ status_code = 404 , detail = "User not found"
268+ ) # user doesn't exist
269+
270+ if user .hackatime_id :
271+ raise HTTPException (
272+ status_code = 400 , detail = "User already has a linked Hackatime ID"
273+ )
274+
275+ hackatime_data = None
276+ try :
277+ hackatime_data = get_account (user_email )
278+ except Exception as e : # type: ignore # pylint: disable=broad-exception-caught
279+ error ("Error fetching Hackatime account data:" , exc_info = e )
280+ raise HTTPException (
281+ status_code = 500 , detail = "Error fetching Hackatime account data"
282+ ) from e
283+
284+ if not hackatime_data :
285+ raise HTTPException (
286+ status_code = 404 , detail = "Hackatime account not found"
287+ )
288+
289+ user .hackatime_id = hackatime_data .id
290+ user .username = hackatime_data .username
291+
292+ try :
293+ await session .commit ()
294+ await session .refresh (user )
295+ return Response (status_code = 204 )
296+ except Exception as e : # type: ignore # pylint: disable=broad-exception-caught
297+ await session .rollback ()
298+ error ("Error linking Hackatime account:" , exc_info = e )
299+ raise HTTPException (
300+ status_code = 500 , detail = "Error linking Hackatime account"
301+ ) from e
302+
303+ # disabled for 30 days, no login -> delete
254304# @protect
255305async def is_pending_deletion ():
256306 """Check if a user account is pending deletion"""
0 commit comments