Skip to content

Commit e0e31b9

Browse files
committed
rewrite words.py to track words per-day (in it's own table)
1 parent c0af477 commit e0e31b9

File tree

2 files changed

+133
-44
lines changed

2 files changed

+133
-44
lines changed

migration/v01.19.0-words.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Used to migrate word stats from prior to v1.19.0
2+
# usage: $ python3 migration/v01.19.00-words.py ~/.bitbot/bot.db
3+
4+
import argparse
5+
parser = argparse.ArgumentParser(description="Migrate pre-v1.19.0 word stats")
6+
parser.add_argument("database")
7+
args = parser.parse_args()
8+
9+
import datetime, sqlite3
10+
database = sqlite3.connect(args.database)
11+
cursor = database.cursor()
12+
13+
cursor.execute(
14+
"SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='words'")
15+
if cursor.fetchone()[0] == 0:
16+
cursor.execute("""
17+
CREATE TABLE words
18+
(user_id INTEGER, channel_id INTEGER, date TEXT, count INTEGER,
19+
FOREIGN KEY (user_id) REFERENCES users(user_id),
20+
FOREIGN KEY (channel_id) REFERENCES channels(channel_id),
21+
PRIMARY KEY (user_id, channel_id, date))""")
22+
23+
cursor.execute("SELECT user_id, nickname FROM users")
24+
users = dict(cursor.fetchall())
25+
cursor.execute("SELECT server_id, alias FROM servers")
26+
servers = dict(cursor.fetchall())
27+
28+
channels = {}
29+
cursor.execute("SELECT server_id, channel_id, name FROM channels")
30+
for server_id, channel_id, name in cursor.fetchall():
31+
channels[channel_id] = (server_id, name)
32+
print(channels)
33+
34+
date = (datetime.datetime.now().date()-datetime.timedelta(days=1)
35+
).strftime("%Y-%m-%d")
36+
37+
cursor.execute("""
38+
SELECT user_id, channel_id, value FROM user_channel_settings
39+
WHERE setting='words'""")
40+
41+
for user_id, channel_id, count in cursor.fetchall():
42+
nickname = users[user_id]
43+
server_id, channel_name = channels[channel_id]
44+
45+
print("[%s] Migrating %s/%s (%s)" %
46+
(servers[server_id], channel_name, nickname, count))
47+
48+
cursor.execute("""
49+
INSERT INTO words (user_id, channel_id, date, count)
50+
VALUES (?, ?, ?, ?)""", [user_id, channel_id, date, count])
51+
52+
database.commit()
53+
database.close()
54+
55+
print()
56+
print("Migration successful!")

modules/words.py

Lines changed: 77 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,59 @@
1717
@utils.export("channelset", utils.BoolSetting("words-prevent-highlight",
1818
"Whether or not to prevent highlights in wordiest lists"))
1919
class Module(ModuleManager.BaseModule):
20+
def on_load(self):
21+
if not self.bot.database.has_table("words"):
22+
self.bot.database.execute("""CREATE TABLE words
23+
(user_id INTEGER, channel_id INTEGER, date TEXT, count INTEGER,
24+
FOREIGN KEY (user_id) REFERENCES users(user_id),
25+
FOREIGN KEY (channel_id) REFERENCES channels(channel_id),
26+
PRIMARY KEY (user_id, channel_id, date))""")
27+
28+
def _get_words_date(self, user, channel, date):
29+
words = self.bot.database.execute_fetchone("""SELECT count FROM words
30+
WHERE user_id=? AND channel_id=? AND date=?""",
31+
[user.get_id(), channel.id, date])
32+
return (words or [0])[0]
33+
def _set_words_date(self, user, channel, date, count):
34+
self.bot.database.execute("""
35+
INSERT OR REPLACE INTO words (user_id, channel_id, date, count)
36+
VALUES (?, ?, ?, ?)""", [user.get_id(), channel.id, date, count])
37+
38+
def _channel_between_dates(self, channel, date1, date2):
39+
return self.bot.database.execute_fetchall("""
40+
SELECT user_id, count FROM words
41+
WHERE channel_id=? AND date>=? AND date<=?""",
42+
[channel.id, date1, date2])
43+
def _channel_all(self, channel):
44+
return self.bot.database.execute_fetchall(
45+
"SELECT user_id, count FROM words WHERE channel_id=?",
46+
[channel.id])
47+
48+
def _user_between_dates(self, user, channel, date1, date2):
49+
return self.bot.datebase.execute_fetchall("""
50+
SELECT count FROM words
51+
WHERE user_id=? AND channel_id=? AND date>=? AND date<=?""",
52+
[user.get_id(), channel.id, date1, date2])
53+
def _user_all(self, user):
54+
return self.bot.database.execute_fetchall(
55+
"SELECT channel_id, count FROM words WHERE user_id=?",
56+
[user.get_id()])
57+
2058
def _channel_message(self, user, event):
2159
if not event["channel"].get_setting("word-tracking", True
2260
) or not user.get_setting("word-tracking", True):
2361
return
2462

25-
words = list(filter(None, event["message_split"]))
26-
word_count = len(words)
27-
28-
user_words = event["channel"].get_user_setting(user.get_id(),
29-
"words", 0)
30-
user_words += word_count
31-
3263
if user.get_setting("first-words", None) == None:
3364
user.set_setting("first-words", time.time())
3465

35-
event["channel"].set_user_setting(user.get_id(), "words", user_words)
66+
words = list(filter(None, event["message_split"]))
67+
word_count = len(words)
68+
69+
date = utils.datetime.format.date_human(utils.datetime.utcnow())
70+
user_words = self._get_words_date(event["user"], event["channel"], date)
71+
self._set_words_date(event["user"], event["channel"], date,
72+
user_words+word_count)
3673

3774
tracked_words = set(event["server"].get_setting(
3875
"tracked-words", []))
@@ -60,32 +97,28 @@ def self_channel_message(self, event):
6097
event["server"].nickname), event)
6198

6299
@utils.hook("received.command.words", channel_only=True)
100+
@utils.kwarg("help",
101+
"See how many words you or the given nickname have used")
102+
@utils.spec("!-channelonly ?<nickname>ouser")
63103
def words(self, event):
64-
"""
65-
:help: See how many words you or the given nickname have used
66-
:usage: [nickname]
67-
"""
68-
if event["args_split"]:
69-
target = event["server"].get_user(event["args_split"
70-
][0])
71-
else:
72-
target = event["user"]
73-
words = dict(target.get_channel_settings_per_setting(
74-
"words", []))
75-
this_channel = words.get(event["target"].name, 0)
104+
target_user = event["spec"][0] or event["user"]
105+
106+
words = dict(self._user_all(target_user))
107+
this_channel = words.get(event["target"].id, 0)
76108

77109
total = 0
78-
for channel in words:
79-
total += words[channel]
110+
for channel_id in words:
111+
total += words[channel_id]
80112

81113
since = ""
82-
first_words = target.get_setting("first-words", None)
114+
first_words = target_user.get_setting("first-words", None)
83115
if not first_words == None:
84116
since = " since %s" % utils.datetime.format.date_human(
85117
utils.datetime.timestamp(first_words))
86118

87119
event["stdout"].write("%s has used %d words (%d in %s)%s" % (
88-
target.nickname, total, this_channel, event["target"].name, since))
120+
target_user.nickname, total, this_channel, event["target"].name,
121+
since))
89122

90123
@utils.hook("received.command.trackword", min_args=1)
91124
def track_word(self, event):
@@ -138,32 +171,32 @@ def word_users(self, event):
138171
event["stderr"].write("That word is not being tracked")
139172

140173
@utils.hook("received.command.wordiest")
174+
@utils.spec("!-channelonly ?<start>date ?<end>date")
141175
def wordiest(self, event):
142176
"""
143177
:help: Show wordiest users
144-
:usage: [channel]
178+
:usage: [startdate
145179
"""
146-
channel_query = None
147-
word_prefix = ""
148-
if event["args"]:
149-
if not event["args_split"][0] == "*":
150-
channel_query = event["args_split"][0].lower()
151-
elif event["is_channel"]:
152-
channel_query = event["target"].name
153-
154-
if channel_query:
155-
word_prefix = " (%s)" % channel_query
156-
157-
words = event["server"].find_all_user_channel_settings("words")
180+
181+
date_str = ""
182+
183+
if event["spec"][0]:
184+
date1 = utils.datetime.format.date_human(event["spec"][0])
185+
date2 = utils.datetime.format.date_human(
186+
event["spec"][1] or utils.datetime.utcnow())
187+
188+
date_str = f" ({date1} to {date2})"
189+
words = self._channel_between_dates(event["target"], date1, date2)
190+
else:
191+
words = self._channel_all(event["target"])
192+
158193
user_words = {}
159-
for channel_name, nickname, word_count in words:
160-
if not channel_query or channel_name == channel_query:
161-
if not nickname in user_words:
162-
user_words[nickname] = 0
163-
user_words[nickname] += word_count
194+
for user_id, word_count in words:
195+
_, nickname = self.bot.database.users.by_id(user_id)
196+
user_words[nickname] = word_count
164197

165198
top_10 = utils.top_10(user_words,
166199
convert_key=lambda nickname: self._get_nickname(
167200
event["server"], event["target"], nickname))
168-
event["stdout"].write("wordiest%s: %s" % (
169-
word_prefix, ", ".join(top_10)))
201+
event["stdout"].write("wordiest in %s%s: %s" %
202+
(str(event["target"]), date_str, ", ".join(top_10)))

0 commit comments

Comments
 (0)