[1mdiff --git a/50_bubble.py b/50_bubble.py[m
[1mindex 61d83bc..bfa699b 100644[m
[1m--- a/50_bubble.py[m
[1m+++ b/50_bubble.py[m
[36m@@ -18,7 +18,7 @@[m [mfrom utils import *[m
from worker import *[m
[m
[m
[31m-version = '8.1'[m
[32m+[m[32m__version__ = '8.2'[m
[m
[m
class Bubble:[m
[36m@@ -961,6 +961,9 @@[m [mDeleting a subspace will delete all posts and comments in the subspace, i.e., th[m
if session.user and session.user.flags & User.HOME_FOLLOWED_FEED_FLAG \[m
else 'all'[m
[m
[32m+[m[32m elif req.path == self.path + 'stats':[m
[32m+[m[32m return make_stats_page(session)[m
[32m+[m
else:[m
return 51, "Not found"[m
[m
[1mdiff --git a/admin.py b/admin.py[m
[1mindex da01c48..bb7b351 100644[m
[1m--- a/admin.py[m
[1m+++ b/admin.py[m
[36m@@ -222,3 +222,20 @@[m [mdef admin_actions(session):[m
page += f'\n=> {session.path}admin/ Back to Administration\n'[m
[m
return page[m
[32m+[m
[32m+[m
[32m+[m[32mdef make_stats_page(session):[m
[32m+[m[32m db = session.db[m
[32m+[m[32m page = '# Statistics\n\n'[m
[32m+[m[32m stats = db.get_statistics()[m
[32m+[m[32m page += f"""```Table: Accounts and activity[m
[32m+[m[32mTotal accounts │ {stats['total']:4d}[m
[32m+[m[32mTotal posters │ {stats['posters']:4d}[m
[32m+[m[32mTotal commenters │ {stats['commenters']:4d}[m
[32m+[m[32mVisited <= 30 days │ {stats['m_visited']:4d}[m
[32m+[m[32mPost/comment <= 30 days │ {stats['m_post_cmt']:4d}[m
[32m+[m[32m```[m
[32m+[m
[32m+[m[32m=> {session.path} Back to front page\n[m
[32m+[m[32m"""[m
[32m+[m[32m return page[m
\ No newline at end of file[m
[1mdiff --git a/model.py b/model.py[m
[1mindex 18a102d..9f3a7af 100644[m
[1m--- a/model.py[m
[1m+++ b/model.py[m
[36m@@ -2886,6 +2886,25 @@[m [mclass Database:[m
cur.execute("INSERT INTO log (remote, type) VALUES (?, ?)", (address_hash(from_addr), type))[m
self.commit()[m
[m
[32m+[m[32m def get_statistics(self):[m
[32m+[m[32m cur = self.conn.cursor()[m
[32m+[m[32m cur.execute("""SELECT[m
[32m+[m[32m (SELECT COUNT(id) FROM users) AS total,[m
[32m+[m[32m (SELECT COUNT(id) FROM users WHERE TIMESTAMPDIFF(DAY, ts_active, CURRENT_TIMESTAMP()) <= 30) AS m_visited,[m
[32m+[m[32m (SELECT COUNT(DISTINCT(user)) FROM posts WHERE TIMESTAMPDIFF(DAY, ts_created, CURRENT_TIMESTAMP()) <= 30) AS m_post_cmt,[m
[32m+[m[32m (SELECT COUNT(DISTINCT(user)) FROM posts WHERE parent=0) AS posters,[m
[32m+[m[32m (SELECT COUNT(DISTINCT(user)) FROM posts WHERE parent!=0) AS commenters[m
[32m+[m[32m """)[m
[32m+[m[32m for (total, m_visited, m_post_cmt, posters, commenters) in cur:[m
[32m+[m[32m return {[m
[32m+[m[32m 'total': total,[m
[32m+[m[32m 'posters': posters,[m
[32m+[m[32m 'commenters': commenters,[m
[32m+[m[32m 'm_visited': m_visited,[m
[32m+[m[32m 'm_post_cmt': m_post_cmt[m
[32m+[m[32m }[m
[32m+[m[32m return {}[m
[32m+[m
[m
class Search:[m
def __init__(self, db):[m
text/plain
This content has been proxied by September (3851b).