Commit c3bd4bd8 authored by Mindiell's avatar Mindiell

Added more comments; Added mastering of rp; Fibonacci sequence for begging op mode

parent 3fe8fc46
......@@ -6,3 +6,8 @@ INSERT INTO moderator VALUES ('Mindiell');
CREATE TABLE tweets (last_entry_published varchar(40));
INSERT INTO tweets VALUES ('2015-01-01 00:00:00 UTC');
CREATE TABLE wiki (last_entry_published varchar(40));
INSERT INTO wiki VALUES ('2015-01-01 00:00:00 UTC');
CREATE TABLE rpator (name varchar(50), score int);
......@@ -47,15 +47,6 @@ messages = {
"rp_http":
"""Merci %s, mais je prends en compte uniquement les adresses internet qui commencent par http ou https""",
"rp_new_article":
"""Merci %s, cette url a été ajoutée à la revue de presse ! À présent, que dirais-tu d'aider à choisir les extraits de l'article à publier sur #lqdn-rp ? <3""",
"rp_known_article":
"""Merci %s ! Un point a été ajouté à cet article : à partir de 3, il pourra être repris dans la revue de presse. D'ailleurs, que dirais-tu d'aider à choisir les extraits à publier sur #lqdn-rp ? <3""",
"rp_taken_article":
"""Merci %s ! Un point a été ajouté à cet article : il va être repris dans la revue de presse. D'ailleurs, que dirais-tu d'aider à choisir les extraits à publier sur #lqdn-rp ? <3""",
"status_unknown_article":
"""Désolé %s, l'url donnée n'existe pas dans la base de données.""",
......@@ -113,5 +104,32 @@ messages = {
"coin_deltree":
"""%s ~ %s ~ Deltree ~ %s ~ %s""",
"new_rp_new_article":
"""Merci %s, cette url a été ajoutée à la revue de presse ! À présent, que dirais-tu d'aider à choisir les extraits de l'article à publier sur #lqdn-rp ? <3""",
"new_rp_known_article":
"""Merci %s ! Un point a été ajouté à cet article : à partir de 3, il pourra être repris dans la revue de presse. D'ailleurs, que dirais-tu d'aider à choisir les extraits à publier sur #lqdn-rp ? <3""",
"new_rp_taken_article":
"""Merci %s ! Un point a été ajouté à cet article : il va être repris dans la revue de presse. D'ailleurs, que dirais-tu d'aider à choisir les extraits à publier sur #lqdn-rp ? <3""",
"known_rp_new_article":
"""Merci %s, cette url a été ajoutée à la revue de presse !""",
"known_rp_known_article":
"""Merci %s ! Un point a été ajouté à cet article : à partir de 3, il pourra être repris dans la revue de presse.""",
"known_rp_taken_article":
"""Merci %s ! Un point a été ajouté à cet article : il va être repris dans la revue de presse.""",
"master_rp_new_article":
"""Merci pour l'info %s !""",
"master_rp_known_article":
"""Merci %s !""",
"master_rp_taken_article":
"""Merci %s ! L'article est prêt pour la revue de presse !""",
}
......@@ -27,6 +27,9 @@ INFO = 1
ERROR = 0
LOG_LEVEL = DEBUG
MASTER_SCORE = 5
MASTER_CLEANING = 7 # in days
animals = [
{
"left": """><((('>""",
......@@ -182,10 +185,23 @@ class Wantzel(object):
"""
Initialization of bot over IRC.
"""
# Date of next cleaning
next_week = time.localtime(time.mktime(time.localtime())+(MASTER_CLEANING*86400))
self.next_cleaning = time.strptime("%s-%s-%s %s" % (
next_week.tm_year,
next_week.tm_mon,
next_week.tm_mday,
time.tzname[0]
), "%Y-%m-%d %Z")
# Sequence for op_mode verification
self.op_sequence = [2, 3, 5, 8, 13, 21, 34, 55]
self.op_offset = 0
self.op_counter = 0
# Number of articles actually waiting
self.number = None
# default last_entry_published for tweets
self.last_entry_published = time.strptime("2000-01-01", "%Y-%m-%d")
# See if there is something in the db
# See if there is a later last_entry_published for tweets
connection = sqlite3.connect(config.sqlite_db)
for row in connection.execute("SELECT last_entry_published FROM tweets"):
self.last_entry_published = time.strptime(
......@@ -195,7 +211,7 @@ class Wantzel(object):
Utils.debug("Dernier tweet: %s" % self.last_entry_published)
# default last_entry_published for wiki
self.last_entry_updated = time.strptime("2000-01-01", "%Y-%m-%d")
# See if there is something in the db
# See if there is a later last_entry_published for wiki
connection = sqlite3.connect(config.sqlite_db)
for row in connection.execute("SELECT last_entry_updated FROM wikis"):
self.last_entry_updated = time.strptime(
......@@ -204,6 +220,7 @@ class Wantzel(object):
)
Utils.debug("Dernière mise à jour du wiki: %s" % self.last_entry_updated)
# Connection to IRC
self.irc = IrcClientFactory(config)
self.irc.set_privmsg = self.set_privmsg
reactor.connectTCP(config.server, config.port, self.irc)
......@@ -215,11 +232,18 @@ class Wantzel(object):
This method launches function regularly (see config.timer).
"""
Utils.debug("Timer called")
# Tweet some RP based on french and english feeds
self.rp_to_twitter("http://www.laquadrature.net/fr/revue-de-presse/feed")
self.rp_to_twitter("http://www.laquadrature.net/en/press-review/feed")
# Update topice based on number of articles waiting in queue
self.count_articles()
# Verify op mode
self.op_verification()
# Tell on channel if wiki was modified since last time
self.wiki_updates()
# Cleaning points of mastering rp
if time.localtime()>next_cleaning:
self.clean_master_rp()
# Recalling the timer
reactor.callLater(config.timer, self.timer)
......@@ -227,34 +251,64 @@ class Wantzel(object):
"""
This method set the methods to call for each callback received from IRC.
"""
# When receiving a message
self.irc.client.privmsg = self.on_privmsg
self.irc.client.irc_unknown = self.test_unknown
# When the bot discover it is no more op
self.irc.client.irc_unknown = self.irc_unknown
# When bot mode is changed
self.irc.client.modeChanged = self.mode_changed
def test_unknown(self, prefix, command, params):
Utils.debug("UNKNOWN %s %s %s" % (prefix, command, params))
if command=="RPL_NAMREPLY":
self.names(params)
def op_verification(self):
def mode_changed(self, user, channel, flag_set, modes, args):
"""
Verify if wantzel is chan operator, if not it complains on the chan <3.
Callback called whenever bot mode is changed.
"""
Utils.debug("op_verification method")
# On liste les utilisateurs du canal de la rp
self.irc.client.sendLine("NAMES #lqdn-rp")
def mode_changed(self, user, channel, flag_set, modes, args):
Utils.debug("Mode changed : %s %s %s %s %s" % (user, channel, flag_set, modes, args))
if "o" in modes and self.irc.client.nickname in args:
# Cleaning user name
user = re.search("([^!]*)!", user).group(1)
if flag_set:
# thanks to user
self.send_message(channel, messages["oped"] % user)
# reset sequence
self.op_offset = 0
else:
# bad user ;o(
self.send_message(channel, messages["deoped"] % user)
def op_verification(self):
"""
Verify if wantzel is chan operator, if not it complains on the chan <3.
"""
Utils.debug("op_verification method")
# Testing based on fibonacci sequence
self.op_counter += 1
if self.op_counter>self.op_sequence[sel.op_offset]:
# Bot tries to list channel users, if it can't, then it is no more an op
self.irc.client.sendLine("NAMES #lqdn-rp")
def irc_unknown(self, prefix, command, params):
"""
This Callback is called whenever the bot tries to perform the command "NAMES" on the
#lqdn-rp channel. If it occurs, then the bot knows that it is no more op and beg for
a mode change to actual operators on the channel.
"""
Utils.debug("UNKNOWN %s %s %s" % (prefix, command, params))
if command=="RPL_NAMREPLY":
# Beg for operator mode
self.names(params)
# Then move the sequence further in order not to spam channel
if self.op_offset<len(self.op_sequence):
self.op_offset += 1
def names(self, params):
"""
Send a message on channel #lqdn-rp to beg an op mode to each actual operators.
params is an array with :
- params[0]:
- params[1]:
- params[2]: the channel
- params[3]: the list of all users on the channel
"""
Utils.debug("Names : %s" % params)
if params[2]=="#lqdn-rp":
ops = [user[1:] for user in params[3].split() if user[0]=="@"]
......@@ -276,8 +330,9 @@ class Wantzel(object):
Returns a message about how to use the bot.
If a command is passed after help, the message explains how to use
the command.
Bot answers in private in order not to spam channel
- rp(acp) <url>
Add an article in the database
Add an article in the database with a specific flag
- status <url>
Retrieve some informations about an article in the database
- stats
......@@ -297,7 +352,7 @@ class Wantzel(object):
user = re.search("([^!]*)!", user).group(1)
Utils.debug("Message received: %s %s %s" % (user, channel, msg))
# Never answer to botself
if user != config.nickname:
if user!=config.nickname:
# If it's a query, bot should answer to the user as the channel
if "#" not in channel:
channel = user
......@@ -329,6 +384,8 @@ class Wantzel(object):
elif command == "admin":
Utils.debug("Calling self.admin")
self.admin(user, channel, msg)
# Very specific command for fun only. You can easily garbage or
# comment the next few lines
if user.lower()=="deltree" and msg=="\_o< ~ Coin ~ >o_/":
animal = random.choice(animals)
self.send_message(channel, messages["coin_deltree"] % (
......@@ -337,6 +394,8 @@ class Wantzel(object):
animal["sound"],
animal["right"],
))
# End of fun command.
# No more giving the title of an url
#if title and website:
# self.send_message(channel, messages["title"] % (title, website))
......@@ -366,6 +425,7 @@ class Wantzel(object):
Utils.debug("rp msg : %s" % msg)
cite = 0
note = 1
answer = False
url = get_url(msg)
Utils.debug("url: %s" % url)
if not url:
......@@ -406,7 +466,7 @@ class Wantzel(object):
""",
(url, user, cite, note)
)
self.send_message(channel, messages["rp_new_article"] % user)
answer = True
else:
if rows[0][2] != user:
Utils.debug("Adding a point by %s on %s" % (user, rows[0][0]))
......@@ -414,12 +474,82 @@ class Wantzel(object):
"UPDATE presse SET note=note+1 WHERE id=%s",
(rows[0][0], )
)
if (rows[0][1]+1) < 3:
self.send_message(channel, messages["rp_known_article"] % user)
else:
self.send_message(channel, messages["rp_taken_article"] % user)
note = rows[0][1]+1
answer = True
if note>=3:
# Update number of articles to do
self.count_articles()
if answer:
# Answer is now based on where, who, note, and a little magic
self.did_rp(channel, user, note)
def did_rp(self, channel, user, note):
"""
Answers after a "rp" command has been submitted. The answer is based on the channel, the
user and the note of the article.
"""
know_rp = False
known_user = False
master_user = False
# Retrieve user's score in database
connection = sqlite3.connect(config.sqlite_db)
score = 0
for row in connection.execute("SELECT score FROM rpator WHERE user='%s'" % user):
known_user = True
score = int(row[0])
if score>MASTER_SCORE:
master_user = True
# Store new score for this user
if known_user:
connection.execute("UPDATE rpator SET score=score+1 WHERE user='%s'" % user)
else:
connection.execute("INSERT INTO rpator (name, score) VALUES ('%s', 1)" % user)
# Channel is #lqdn-rp, so the user is knowing the rp yet
if channel=="#lqdn-rp":
know_rp = True
# Ok, we got all information we need, let's answer now !
if master_user:
# user is a rp master
if note==1:
self.send_message(channel, messages["master_rp_new_article"] % user)
elif note<3:
self.send_message(channel, messages["master_rp_known_article"] % user)
else:
self.send_message(channel, messages["master_rp_taken_article"] % user)
elif known_user or know_rp:
# user is known but not a master and/or he knows the rp channel
if note==1:
self.send_message(channel, messages["known_rp_new_article"] % user)
elif note<3:
self.send_message(channel, messages["known_rp_known_article"] % user)
else:
self.send_message(channel, messages["known_rp_taken_article"] % user)
else:
# user is unknown, and he does'nt seems to know the rp channel
if note==1:
self.send_message(channel, messages["new_rp_new_article"] % user)
elif note<3:
self.send_message(channel, messages["new_rp_known_article"] % user)
else:
self.send_message(channel, messages["new_rp_taken_article"] % user)
def clean_master_rp(self):
"""
This method cleans the known user from rp_mastering each 7 days
"""
# Cleaning users
connection = sqlite3.connect(config.sqlite_db)
connection.execute("UPDATE rpator SET score=score-1 WHERE user='%s'" % user)
connection.execute("DELETE FROM rpator WHERE score<1")
# Date of next cleaning
next_week = time.localtime(time.mktime(time.localtime())+(MASTER_CLEANING*86400))
self.next_cleaning = time.strptime("%s-%s-%s %s" % (
next_week.tm_year,
next_week.tm_mon,
next_week.tm_mday,
time.tzname[0]
), "%Y-%m-%d %Z")
def status(self, command, user, channel, msg):
"""
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment