Rthur2003 commited on
Commit
fcfa3d9
·
1 Parent(s): 4d426bf

feat: implement Comment Tracker Service to manage posted video IDs and prevent duplicate comments

Browse files
Files changed (1) hide show
  1. app/routes/commend/comment_tracker.py +117 -0
app/routes/commend/comment_tracker.py ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Comment Tracker Service for Crown Commend
3
+ Tracks posted video IDs to prevent duplicate comments (anti-spam/bot protection).
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ import json
9
+ import os
10
+ from datetime import datetime
11
+ from pathlib import Path
12
+ from typing import Optional, Dict, Any
13
+ from threading import Lock
14
+
15
+ from ...services.logging_config import get_logger
16
+
17
+ logger = get_logger(__name__)
18
+
19
+ # Thread-safe lock for file operations
20
+ _file_lock = Lock()
21
+
22
+ # Storage path - use /data for HF Spaces persistence, fallback to local
23
+ def _get_storage_path() -> Path:
24
+ """Get the path for storing comment history."""
25
+ # HF Spaces persistent storage
26
+ if os.path.exists('/data'):
27
+ return Path('/data/commend_history.json')
28
+ # Local development
29
+ return Path(__file__).parent / 'commend_history.json'
30
+
31
+
32
+ def _load_history() -> Dict[str, Any]:
33
+ """Load comment history from file."""
34
+ path = _get_storage_path()
35
+ try:
36
+ if path.exists():
37
+ with open(path, 'r', encoding='utf-8') as f:
38
+ return json.load(f)
39
+ except (json.JSONDecodeError, IOError) as e:
40
+ logger.warning(f"Could not load history: {e}")
41
+ return {"posted_videos": {}}
42
+
43
+
44
+ def _save_history(history: Dict[str, Any]) -> bool:
45
+ """Save comment history to file."""
46
+ path = _get_storage_path()
47
+ try:
48
+ # Ensure directory exists
49
+ path.parent.mkdir(parents=True, exist_ok=True)
50
+ with open(path, 'w', encoding='utf-8') as f:
51
+ json.dump(history, f, ensure_ascii=False, indent=2)
52
+ return True
53
+ except IOError as e:
54
+ logger.error(f"Could not save history: {e}")
55
+ return False
56
+
57
+
58
+ def is_video_commented(video_id: str) -> bool:
59
+ """Check if a comment has already been posted to this video."""
60
+ with _file_lock:
61
+ history = _load_history()
62
+ return video_id in history.get("posted_videos", {})
63
+
64
+
65
+ def get_video_comment_info(video_id: str) -> Optional[Dict[str, Any]]:
66
+ """Get comment info for a video if it exists."""
67
+ with _file_lock:
68
+ history = _load_history()
69
+ return history.get("posted_videos", {}).get(video_id)
70
+
71
+
72
+ def mark_video_commented(
73
+ video_id: str,
74
+ comment_id: str,
75
+ video_title: Optional[str] = None
76
+ ) -> bool:
77
+ """
78
+ Mark a video as commented.
79
+
80
+ Args:
81
+ video_id: YouTube video ID
82
+ comment_id: The posted comment's ID from YouTube
83
+ video_title: Optional video title for reference
84
+
85
+ Returns:
86
+ True if successfully saved
87
+ """
88
+ with _file_lock:
89
+ history = _load_history()
90
+
91
+ if "posted_videos" not in history:
92
+ history["posted_videos"] = {}
93
+
94
+ history["posted_videos"][video_id] = {
95
+ "comment_id": comment_id,
96
+ "video_title": video_title,
97
+ "posted_at": datetime.utcnow().isoformat() + "Z",
98
+ }
99
+
100
+ # Keep stats
101
+ history["total_comments"] = len(history["posted_videos"])
102
+ history["last_updated"] = datetime.utcnow().isoformat() + "Z"
103
+
104
+ success = _save_history(history)
105
+ if success:
106
+ logger.info(f"Marked video {video_id} as commented")
107
+ return success
108
+
109
+
110
+ def get_comment_stats() -> Dict[str, Any]:
111
+ """Get comment statistics."""
112
+ with _file_lock:
113
+ history = _load_history()
114
+ return {
115
+ "total_comments": len(history.get("posted_videos", {})),
116
+ "last_updated": history.get("last_updated")
117
+ }