11#!/usr/bin/env python3
22"""
3- Basic Memory Daily Traction Report - Enhanced with Growth Tracking
4- Automated tracking across GitHub, Reddit , YouTube with daily change indicators
3+ Basic Memory Daily Traction Report - Clean Version
4+ Automated tracking across GitHub, Discord , YouTube, and Reddit
55"""
66
77import os
@@ -17,13 +17,15 @@ class BasicMemoryTracker:
1717 def __init__ (self ):
1818 self .github_token = os .getenv ('GITHUB_TOKEN' )
1919 self .discord_webhook = os .getenv ('DISCORD_WEBHOOK' )
20+ self .discord_bot_token = os .getenv ('DISCORD_BOT_TOKEN' )
21+ self .discord_server_id = os .getenv ('DISCORD_SERVER_ID' )
2022 self .youtube_api_key = os .getenv ('YOUTUBE_API_KEY' )
2123
2224 # Reddit setup
2325 self .reddit = praw .Reddit (
2426 client_id = os .getenv ('REDDIT_CLIENT_ID' ),
2527 client_secret = os .getenv ('REDDIT_SECRET' ),
26- user_agent = 'BasicMemoryTracker:v1 .0'
28+ user_agent = 'BasicMemoryTracker:v2 .0'
2729 )
2830
2931 # YouTube setup
@@ -106,13 +108,13 @@ def calculate_change(self, current, previous, key):
106108 def format_change (self , change , direction ):
107109 """Format the change indicator for display"""
108110 if direction == "🆕" :
109- return "🆕"
111+ return "" # Don't show change on first run
110112 elif direction == "📈" :
111113 return f"(+{ change } )"
112114 elif direction == "📉" :
113115 return f"(-{ change } )"
114116 else :
115- return "(±0)"
117+ return "" # Don't show (±0)
116118
117119 def get_github_metrics (self ):
118120 """Get GitHub repository metrics"""
@@ -129,61 +131,55 @@ def get_github_metrics(self):
129131 traffic_response = requests .get (traffic_url , headers = headers )
130132 traffic_data = traffic_response .json () if traffic_response .status_code == 200 else {}
131133
132- # Recent issues
133- issues_url = f'https://api.github.com/repos/{ self .repo_owner } /{ self .repo_name } /issues'
134- issues_response = requests .get (issues_url , headers = headers )
135- issues_data = issues_response .json () if issues_response .status_code == 200 else []
136-
137134 return {
138135 'stars' : repo_data .get ('stargazers_count' , 0 ),
139136 'forks' : repo_data .get ('forks_count' , 0 ),
140- 'watchers' : repo_data .get ('watchers_count' , 0 ),
141- 'open_issues' : repo_data .get ('open_issues_count' , 0 ),
142- 'traffic_views' : traffic_data .get ('count' , 0 ),
143- 'traffic_unique' : traffic_data .get ('uniques' , 0 ),
144- 'recent_issues' : len ([i for i in issues_data if
145- parser .parse (i ['created_at' ]).date () >= (datetime .now () - timedelta (days = 1 )).date ()])
137+ 'traffic_unique' : traffic_data .get ('uniques' , 0 ) if traffic_data .get ('uniques' , 0 ) > 0 else None
146138 }
147139 except Exception as e :
148140 print (f"GitHub API error: { e } " )
149141 return {'error' : str (e )}
150142
143+ def get_discord_metrics (self ):
144+ """Get Discord server metrics"""
145+ try :
146+ headers = {'Authorization' : f'Bot { self .discord_bot_token } ' }
147+ guild_url = f'https://discord.com/api/v10/guilds/{ self .discord_server_id } '
148+
149+ response = requests .get (guild_url , headers = headers )
150+
151+ if response .status_code == 200 :
152+ guild_data = response .json ()
153+ return {
154+ 'members' : guild_data .get ('approximate_member_count' , 0 )
155+ }
156+ else :
157+ print (f"Discord API error: { response .status_code } " )
158+ return {'members' : 0 }
159+
160+ except Exception as e :
161+ print (f"Discord API error: { e } " )
162+ return {'members' : 0 }
163+
151164 def get_reddit_metrics (self ):
152- """Get Reddit metrics for Basic Memory mentions """
165+ """Get Reddit metrics for r/BasicMemory only """
153166 try :
154167 metrics = {
155- 'total_mentions' : 0 ,
156- 'subreddit_members' : 0 ,
157- 'top_posts' : [],
158- 'hot_discussions' : []
168+ 'subreddit_members' : 0
159169 }
160170
161- # Search for Basic Memory mentions
162- search_results = list (self .reddit .subreddit ('all' ).search (
163- 'Basic Memory' , time_filter = 'day' , limit = 25
164- ))
165- metrics ['total_mentions' ] = len (search_results )
166-
167- # Get top posts
168- for post in search_results [:3 ]:
169- metrics ['top_posts' ].append ({
170- 'title' : post .title [:50 ] + '...' if len (post .title ) > 50 else post .title ,
171- 'score' : post .score ,
172- 'subreddit' : post .subreddit .display_name ,
173- 'num_comments' : post .num_comments
174- })
175-
176171 # Check r/BasicMemory if it exists
177172 try :
178173 basic_memory_sub = self .reddit .subreddit ('BasicMemory' )
179174 metrics ['subreddit_members' ] = basic_memory_sub .subscribers
180- except :
175+ except Exception as e :
176+ print (f"r/BasicMemory not found or error: { e } " )
181177 metrics ['subreddit_members' ] = 0
182178
183179 return metrics
184180 except Exception as e :
185181 print (f"Reddit API error: { e } " )
186- return {'error ' : str ( e ) }
182+ return {'subreddit_members ' : 0 }
187183
188184 def get_youtube_metrics (self ):
189185 """Get YouTube channel metrics"""
@@ -241,76 +237,79 @@ def get_youtube_metrics(self):
241237 }
242238
243239 def create_discord_embed (self , current_metrics , previous_metrics ):
244- """Create beautiful Discord embed with all metrics and growth indicators"""
240+ """Create clean Discord embed with all metrics and growth indicators"""
245241
246242 github_data = current_metrics .get ('github' , {})
243+ discord_data = current_metrics .get ('discord' , {})
247244 reddit_data = current_metrics .get ('reddit' , {})
248245 youtube_data = current_metrics .get ('youtube' , {})
249246
250247 prev_github = previous_metrics .get ('github' , {})
248+ prev_discord = previous_metrics .get ('discord' , {})
251249 prev_reddit = previous_metrics .get ('reddit' , {})
252250 prev_youtube = previous_metrics .get ('youtube' , {})
253251
254252 # Calculate changes
255253 star_change , star_dir = self .calculate_change (github_data .get ('stars' , 0 ), prev_github , 'stars' )
254+ discord_change , discord_dir = self .calculate_change (discord_data .get ('members' , 0 ), prev_discord , 'members' )
255+ reddit_change , reddit_dir = self .calculate_change (reddit_data .get ('subreddit_members' , 0 ), prev_reddit , 'subreddit_members' )
256256 sub_change , sub_dir = self .calculate_change (youtube_data .get ('subscribers' , 0 ), prev_youtube , 'subscribers' )
257257 view_change , view_dir = self .calculate_change (youtube_data .get ('total_views' , 0 ), prev_youtube , 'total_views' )
258- reddit_change , reddit_dir = self .calculate_change (reddit_data .get ('total_mentions' , 0 ), prev_reddit , 'total_mentions' )
259- member_change , member_dir = self .calculate_change (reddit_data .get ('subreddit_members' , 0 ), prev_reddit , 'subreddit_members' )
260258
261- # Calculate total reach
262- total_reach = (
263- github_data .get ('traffic_unique' , 0 ) +
264- reddit_data .get ('total_mentions' , 0 ) * 100 +
265- youtube_data .get ('total_views' , 0 )
266- )
259+ # Traffic display logic
260+ traffic_display = "Data pending" if github_data .get ('traffic_unique' ) is None else f"{ github_data .get ('traffic_unique' , 0 )} visitors"
267261
268262 embed = {
269263 "title" : "🚀 Basic Memory Daily Traction Report" ,
270264 "description" : f"📅 { datetime .now ().strftime ('%A, %B %d, %Y' )} " ,
271265 "color" : 0x00ff88 ,
272266 "fields" : [
273267 {
274- "name" : "⭐ GitHub Metrics " ,
268+ "name" : "⭐ GitHub" ,
275269 "value" : f"""
276- **Stars:** { github_data .get ('stars' , 'N/A' )} { star_dir } { self .format_change (star_change , star_dir )}
277- **Forks:** { github_data .get ('forks' , 'N/A' )} 🍴
278- **Traffic:** { github_data .get ('traffic_unique' , 'N/A' )} unique visitors 👀
279- **Issues:** { github_data .get ('recent_issues' , 0 )} new today 🐛
270+ **Stars:** { github_data .get ('stars' , 'N/A' )} { self .format_change (star_change , star_dir )}
271+ **Forks:** { github_data .get ('forks' , 'N/A' )}
272+ **Traffic:** { traffic_display }
280273 """ .strip (),
281274 "inline" : True
282275 },
283276 {
284- "name" : "🗨️ Reddit Activity " ,
277+ "name" : "💬 Community " ,
285278 "value" : f"""
286- **Mentions:** { reddit_data .get ('total_mentions' , 'N/A' )} { reddit_dir } { self .format_change (reddit_change , reddit_dir )}
287- **r/BasicMemory:** { reddit_data .get ('subreddit_members' , 'N/A' )} { member_dir } { self .format_change (member_change , member_dir )}
288- **Hot Posts:** { len (reddit_data .get ('top_posts' , []))} trending 🔥
279+ **Discord:** { discord_data .get ('members' , 'N/A' )} members { self .format_change (discord_change , discord_dir )}
280+ **r/BasicMemory:** { reddit_data .get ('subreddit_members' , 'N/A' )} { self .format_change (reddit_change , reddit_dir )}
289281 """ .strip (),
290282 "inline" : True
291283 },
292284 {
293- "name" : "📺 YouTube Stats " ,
285+ "name" : "📺 YouTube" ,
294286 "value" : f"""
295- **Subscribers:** { youtube_data .get ('subscribers' , 'N/A' )} { sub_dir } { self .format_change (sub_change , sub_dir )}
296- **Total Views:** { youtube_data .get ('total_views' , 'N/A' )} { view_dir } { self .format_change (view_change , view_dir )}
297- **Videos:** { youtube_data .get ('video_count' , 'N/A' )} 🎬
287+ **Subscribers:** { youtube_data .get ('subscribers' , 'N/A' )} { self .format_change (sub_change , sub_dir )}
288+ **Views:** { youtube_data .get ('total_views' , 'N/A' )} { self .format_change (view_change , view_dir )}
289+ **Videos:** { youtube_data .get ('video_count' , 'N/A' )}
298290 """ .strip (),
299291 "inline" : True
300292 }
301293 ],
302294 "footer" : {
303- "text" : f"🤖 Automated by Basic Memory • Daily Reach: { total_reach } "
295+ "text" : f"🤖 Automated by Basic Memory"
304296 },
305297 "timestamp" : datetime .now ().isoformat ()
306298 }
307299
308- # Add top Reddit posts if available
309- if reddit_data .get ('top_posts' ):
310- top_post = reddit_data ['top_posts' ][0 ]
300+ # Add daily highlight if there's significant growth
301+ highlights = []
302+ if discord_change > 5 :
303+ highlights .append (f"Discord gained { discord_change } new members!" )
304+ if star_change > 10 :
305+ highlights .append (f"GitHub stars up { star_change } !" )
306+ if sub_change > 0 :
307+ highlights .append (f"YouTube gained { sub_change } subscribers!" )
308+
309+ if highlights :
311310 embed ["fields" ].append ({
312- "name" : "🔥 Top Reddit Post " ,
313- "value" : f"** { top_post [ 'title' ] } ** \n 📊 { top_post [ 'score' ] } upvotes • 💬 { top_post [ 'num_comments' ] } comments \n 📍 r/ { top_post [ 'subreddit' ] } " ,
311+ "name" : "📈 Today's Highlight " ,
312+ "value" : highlights [ 0 ], # Show the first/most important highlight
314313 "inline" : False
315314 })
316315
@@ -346,6 +345,9 @@ def run_daily_report(self):
346345 print ("📊 Collecting GitHub metrics..." )
347346 github_data = self .get_github_metrics ()
348347
348+ print ("💬 Collecting Discord metrics..." )
349+ discord_data = self .get_discord_metrics ()
350+
349351 print ("🗨️ Collecting Reddit metrics..." )
350352 reddit_data = self .get_reddit_metrics ()
351353
@@ -355,12 +357,13 @@ def run_daily_report(self):
355357 # Combine current metrics
356358 current_metrics = {
357359 'github' : github_data ,
360+ 'discord' : discord_data ,
358361 'reddit' : reddit_data ,
359362 'youtube' : youtube_data
360363 }
361364
362365 # Create and send report
363- print ("🎨 Creating Discord embed with growth tracking ..." )
366+ print ("🎨 Creating clean Discord embed..." )
364367 embed = self .create_discord_embed (current_metrics , previous_metrics .get ('metrics' , {}))
365368
366369 print ("📤 Sending to Discord..." )
@@ -379,9 +382,9 @@ def run_daily_report(self):
379382 print (f"""
380383📊 DAILY SUMMARY:
381384⭐ GitHub Stars: { github_data .get ('stars' , 'Error' )}
382- 👥 Reddit Mentions: { reddit_data .get ('total_mentions' , 'Error' )}
385+ 💬 Discord Members: { discord_data .get ('members' , 'Error' )}
386+ 🗨️ r/BasicMemory: { reddit_data .get ('subreddit_members' , 'Error' )}
383387📺 YouTube Subscribers: { youtube_data .get ('subscribers' , 'Error' )}
384- 📺 YouTube Views: { youtube_data .get ('total_views' , 'Error' )}
385388 """ )
386389
387390if __name__ == "__main__" :
0 commit comments