this repo has no description

feat: resurrect popular

Changed files
+33 -65
feeds
+1 -1
feed_manager.py
··· 47 47 48 48 feed_manager = FeedManager() 49 49 feed_manager.register(RapidFireFeed) 50 - # feed_manager.register(PopularFeed) 50 + feed_manager.register(PopularFeed) 51 51 feed_manager.register(HomeRunsTeamFeed) 52 52 feed_manager.register(NoraZoneInteresting) 53 53 feed_manager.register(SevenDirtyWordsFeed)
+32 -64
feeds/popular.py
··· 9 9 FEED_URI = 'at://did:plc:4nsduwlpivpuur4mqkbfvm6a/app.bsky.feed.generator/popular' 10 10 11 11 def __init__(self): 12 - self.db_cnx = apsw.Connection('db/popular.db') 12 + # use the posts from the most-liked feed for this 13 + self.db_cnx = apsw.Connection('db/mostliked.db') 14 + self.db_cnx.pragma('foreign_keys', True) 13 15 self.db_cnx.pragma('journal_mode', 'WAL') 14 - self.db_cnx.pragma('wal_autocheckpoint', '0') 15 - 16 - with self.db_cnx: 17 - self.db_cnx.execute(""" 18 - create table if not exists posts (uri text, create_ts timestamp, update_ts timestamp, temperature int); 19 - create unique index if not exists uri_idx on posts(uri); 20 - """) 21 - 22 - self.logger = logging.getLogger('feeds.popular') 23 16 24 17 def process_commit(self, commit): 25 - if commit['opType'] != 'c': 26 - return 27 - 28 - if commit['collection'] != 'app.bsky.feed.like': 29 - return 30 - 31 - record = commit.get('record') 32 - if record is None: 33 - return 34 - 35 - ts = self.safe_timestamp(record.get('createdAt')).timestamp() 36 - like_subject_uri = record['subject']['uri'] 37 - 38 - self.transaction_begin(self.db_cnx) 18 + pass 39 19 40 - self.db_cnx.execute(""" 41 - insert into posts (uri, create_ts, update_ts, temperature) 42 - values (:uri, :ts, :ts, 1) 43 - on conflict (uri) do update set temperature = temperature + 1, update_ts = :ts 44 - """, dict(uri=like_subject_uri, ts=ts)) 20 + def commit_changes(self): 21 + pass 45 22 46 - def delete_old_posts(self): 47 - self.db_cnx.execute(""" 48 - delete from posts 23 + def generate_sql(self, limit, offset, langs): 24 + bindings = [] 25 + sql = """ 26 + select posts.uri, create_ts, likes, lang, unixepoch('now') - create_ts as age_seconds, 27 + exp( -1 * ( ( unixepoch('now') - create_ts ) / 1800.0 ) ) as decay, 28 + likes * exp( -1 * ( ( unixepoch('now') - create_ts ) / 1800.0 ) ) as score 29 + from posts 30 + left join langs on posts.uri = langs.uri 49 31 where 50 - temperature * exp( -1 * ( ( unixepoch('now') - create_ts ) / 1800.0 ) ) < 1.0 51 - and create_ts < unixepoch('now', '-15 minutes') 52 - """) 53 - self.logger.debug('deleted {} old posts'.format(self.db_cnx.changes())) 54 - 55 - def commit_changes(self): 56 - self.delete_old_posts() 57 - self.logger.debug('committing changes') 58 - self.transaction_commit(self.db_cnx) 59 - self.wal_checkpoint(self.db_cnx, 'RESTART') 32 + """ 33 + if not '*' in langs: 34 + lang_values = list(langs.values()) 35 + bindings.extend(lang_values) 36 + sql += " OR ".join(['lang = ?'] * len(lang_values)) 37 + else: 38 + sql += " 1=1 " 39 + sql += """ 40 + order by score desc 41 + limit ? offset ? 42 + """ 43 + bindings.extend([limit, offset]) 44 + return sql, bindings 60 45 61 46 def serve_feed(self, limit, offset, langs): 62 - cur = self.db_cnx.execute(""" 63 - select uri from posts 64 - order by temperature * exp( -1 * ( ( unixepoch('now') - create_ts ) / 1800.0 ) ) 65 - desc limit :limit offset :offset 66 - """, dict(limit=limit, offset=offset)) 67 - return [uri for (uri,) in cur] 47 + sql, bindings = self.generate_sql(limit, offset, langs) 48 + cur = self.db_cnx.execute(sql, bindings) 49 + return [row[0] for row in cur] 68 50 69 51 def serve_feed_debug(self, limit, offset, langs): 70 - query = """ 71 - select 72 - uri, temperature, 73 - unixepoch('now') - create_ts as age_seconds, 74 - exp( 75 - -1 * ( ( unixepoch('now') - create_ts ) / 1800.0 ) 76 - ) as decay, 77 - temperature * exp( 78 - -1 * ( ( unixepoch('now') - create_ts ) / 1800.0 ) 79 - ) as score 80 - from posts 81 - order by score desc 82 - limit :limit offset :offset 83 - """ 84 - bindings = dict(limit=limit, offset=offset) 52 + sql, bindings = self.generate_sql(limit, offset, langs) 85 53 return apsw.ext.format_query_table( 86 - self.db_cnx, query, bindings, 54 + self.db_cnx, sql, bindings, 87 55 string_sanitize=2, text_width=9999, use_unicode=True 88 56 )