Commit 80cfaf6a authored by Mindiell's avatar Mindiell

more conversion done

parent acbc8f15
...@@ -10,3 +10,7 @@ password = '', ...@@ -10,3 +10,7 @@ password = '',
channels = [ channels = [
'#testchannel' '#testchannel'
] ]
dbuser = "root"
dbpassword = ""
dbserver = "localhost"
dbname = "db"
...@@ -9,7 +9,7 @@ from twisted.words.protocols import irc ...@@ -9,7 +9,7 @@ from twisted.words.protocols import irc
class IrcClient(irc.IRCClient): class IrcClient(irc.IRCClient):
def __init__(self, config): def __init__(self, config):
self.config = config self.config = config
self.nickname = "TestMan" self.nickname = config.nickname
self.password = config.password self.password = config.password
def connectionMade(self): def connectionMade(self):
......
...@@ -5,24 +5,53 @@ Il les recharge à chaque fois qu'on lui fournit la commande '!reload' sur IRC. ...@@ -5,24 +5,53 @@ Il les recharge à chaque fois qu'on lui fournit la commande '!reload' sur IRC.
""" """
messages = { messages = {
"hello": """Bonjour, je suis le bot de la Quadrature du Net, vous pouvez me demander de l'aide si besoin. (wantzel help)""", "hello":
"""Bonjour, je suis le bot de la Quadrature du Net, vous pouvez me demander de l'aide si besoin. (wantzel help)""",
"help": """Toute l'aide se trouve ici : https://wiki.laquadrature.net/Wantzel""", "help":
"""Mes commandes sont : !help !rp(cpa) !kill !stats.
Pour plus d'informations, voir ici: https://wiki.laquadrature.net/Wantzel
Pour obtenir de l'aide sur une commande en particulier, il suffit de taper !help <commande>""",
"help_rp": """""", "help_help":
"""Bravo!
Tu viens d'entrer dans le monde récursif où l'aide sert à expliciter l'aide.""",
"help_stats": """""", "help_rp":
"""Cette commande sert à ajouter un article à la Revue de Presse (https://wiki.laquadrature.net/Revue_de_presse)
L'utilisation se fait sous la forme: !rp <url de l'article à ajouter>""",
#Plusieurs options sont possibles et cumulables: a, c, p
#l'option a => !rpa permet d'archiver un article (il ne sera pas ajouté à la Revue de Presse""",
"help_quote": """""", "help_stats":
"""Cette commande permet de fournir quelques statistiques sur la Revue de Presse (https://wiki.laquadrature.net/Revue_de_presse)
Les statistiques sont calculées sur des notes supérieurs ou égales à 0, 3, et 4. Et sur les 1, 3, 7, et 15 derniers jours.""",
"help_tc": """""", "help_kill":
"""Fixe la note de l'article donné en paramètre à -100.
Utile en cas d'erreur ou pour s'assurer que l'article ne sera pas publié dans la RP
Utilisation: !kill <url de l'article>
*Attention* seuls les vrais rp-jedis ont accès à cette commande <3""",
"help_kill": """""", "rp_http":
"""Merci %s, mais je prends en compte uniquement les adresses internet qui commencent par http ou https""",
"merci_nouvel_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_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""",
"merci_article_connu": """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_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""",
"merci_article_repris": """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""", "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""",
"kill_none":
"""%s n'existe pas dans la base de données""",
"kill_done":
"""%s mit à -100""",
"stats_bravo":
"""Bravo les neurones, rien en retard depuis ces %s derniers jours!""",
} }
#encoding: utf-8 #encoding: utf-8
""" """
Bot Wantzel de La Quadrature du Net Bot Wantzel from La Quadrature du Net.
Pour utiliser l'accès à une base de données MySQL : License : AGPLv3
- apt-get install libmysqlclient-dev Doc : https://wiki.laquadrature.net/Wantzel
- pip install mysql-python
TODO:
- Ajouter la gestion des droits pour certaines commandes
- Mettre une valeur par défaut pour les champs concernés
- Afficher les titres des urls fournies sur le canal
""" """
from irc import IrcClientFactory from irc import IrcClientFactory
import json
import MySQLdb import MySQLdb
import re import re
from twisted.internet import reactor from twisted.internet import reactor
...@@ -17,6 +20,41 @@ import urllib ...@@ -17,6 +20,41 @@ import urllib
import config import config
from messages import messages from messages import messages
def get_cursor():
"""
This function connects to a database and returns a usable cursor.
"""
db = MySQLdb.connect(
host=config.dbserver,
user=config.dbuser,
passwd=config.dbpassword,
db=config.dbname
)
if db:
return db.cursor()
return None
def get_url(message, command=""):
"""
Retrieve the url behind the command.
"""
# Let's get what is behind the command
result = re.search("!%s ([^ ]*)" % command, message)
if not result:
return ""
url = result.group(1)
# Verify the presence of http
result = re.search("^(https?://)(.+)$", url)
if not result:
return "http"
# Removing anchor if needed
result = re.search("^([^#]*)", url)
if result:
url = result.group(1)
# Removing trackers
url = re.sub("[?&](utm_medium|utm_source|utm_campaign|xtor)=[^&]*", "", url)
return url
class Wantzel(object): class Wantzel(object):
""" """
Wantzel bot. Wantzel bot.
...@@ -35,18 +73,6 @@ class Wantzel(object): ...@@ -35,18 +73,6 @@ class Wantzel(object):
""" """
self.irc.client.privmsg = self.on_privmsg self.irc.client.privmsg = self.on_privmsg
self.irc.client.joined = self.on_joined self.irc.client.joined = self.on_joined
#self.irc.client.left = self.on_left
#self.irc.client.noticed = self.on_noticed
#self.irc.client.modeChanged = self.on_mode_changed
#self.irc.client.kickedFrom = self.on_kicked_from
#self.irc.client.nickChanged = self.on_nick_changed
#self.irc.client.userJoined = self.on_user_joined
#self.irc.client.userLeft = self.on_user_left
#self.irc.client.userQuit = self.on_user_quit
#self.irc.client.userKicked = self.on_user_kicked
#self.irc.client.action = self.on_action
#self.irc.client.topicUpdated = self.on_topic_updated
#self.irc.client.userRenamed = self.on_user_renamed
def send_message(self, channel, messages): def send_message(self, channel, messages):
""" """
...@@ -63,44 +89,47 @@ class Wantzel(object): ...@@ -63,44 +89,47 @@ class Wantzel(object):
If a command is passed after help, the message explains how to use If a command is passed after help, the message explains how to use
the command. the command.
- rp(acp) - rp(acp)
Add an article in the database
- stats - stats
- quote Show some statistics about the RP
- tc
- kill - kill
Kill an article by giving it a score of -100
""" """
# Cleaning user name # Cleaning user name
user = re.search("([^!]*)!", user).group(1) user = re.search("([^!]*)!", user).group(1)
print("Message reçu: %s %s %s" % (user, channel, msg)) print("Message received: %s %s %s" % (user, channel, msg))
# Help command, specific # Never answer to botself
if "wantzel" in msg and ("help" in msg or "aide" in msg): if user!=config.nickname:
self.help(user, channel, msg) # If it's a query, bot should answer to the user as the channel
# Find command with parameters if "#" not in channel:
command = re.search("!(rp[acp]*|quote|tc|kill) ", msg) channel = user
if not command: # Help command, specific
# Find command without parameters if "wantzel" in msg and ("help" in msg or "aide" in msg):
command = re.search("^!(help|stats)$", msg)
if command:
print("Commande reçue: %s" % command.group(1))
command = command.group(1)
if command.startswith("rp"):
self.rp(command, user, channel, msg)
elif command=="help":
self.help(user, channel, msg) self.help(user, channel, msg)
elif command=="kill": # Find known command
self.kill(user, channel, msg) command = re.search("!(rp[acp]*|kill|help|stats)", msg)
elif command=="stats": if command:
self.stats(user, channel, msg) command = command.group(1)
elif command=="quote": print("Command: %s" % command)
self.quote(user, channel, msg) if command.startswith("rp"):
elif command=="tc": self.rp(command, user, channel, msg)
self.tc(user, channel, msg) elif command=="help":
self.help(user, channel, msg)
elif command=="kill":
self.kill(user, channel, msg)
elif command=="stats":
self.stats(user, channel, msg)
def on_joined(self, channel): def on_joined(self, channel):
""" """
Say hello to everyone. Say hello to everyone.
""" """
print("Canal %s rejoint" % channel) print("Joined channel %s" % channel)
self.send_message("#mytipy", messages["hello"]) # Specific message for specific channel
if "hello_"+channel[1:] in messages:
self.send_message(channel, messages["hello_"+channel[1:]])
else:
self.send_message(channel, messages["hello"])
def help(self, user, channel, msg): def help(self, user, channel, msg):
""" """
...@@ -109,7 +138,13 @@ class Wantzel(object): ...@@ -109,7 +138,13 @@ class Wantzel(object):
returned. returned.
""" """
print("help command") print("help command")
self.send_message(channel, messages["help"]) # Searching for a command after help keyword
command = re.search("!help (stats|rp|help|kill)", msg)
if command:
command = command.group(1)
self.send_message(user, messages["help_"+command])
else:
self.send_message(channel, messages["help"])
def rp(self, command, user, channel, msg): def rp(self, command, user, channel, msg):
""" """
...@@ -118,19 +153,16 @@ class Wantzel(object): ...@@ -118,19 +153,16 @@ class Wantzel(object):
print("rp command %s" % command) print("rp command %s" % command)
cite = 0 cite = 0
note = 0 note = 0
# On récupère tout ce qui suit la commande !rp url = get_url(msg, command)
url = re.search("!rp (.*)", msg).group(1)
# On nettoie tout ce qui est http
url = re.search("(https?://)?(.*)", url).group(2)
# On vire l'ancre si elle existe
url = re.search("([^#]*)", url).group(0)
# On se débarasse des trackers
url = re.sub("", "", url)
print("url: %s" % url) print("url: %s" % url)
if url=="":
return
elif url=="http":
self.send_message(channel, messages["rp_http"] % user)
return
# On vérifie ensuite l'existence de l'url dans la base de données # Looking for such an article in database
db = MySQLdb.connect(host="localhost", user="root", passwd="root", db="site") cursor = get_cursor()
cursor = db.cursor()
cursor.execute("SELECT id, note, provenance FROM presse WHERE url = %s", (url, )) cursor.execute("SELECT id, note, provenance FROM presse WHERE url = %s", (url, ))
rows = cursor.fetchall() rows = cursor.fetchall()
if not rows: if not rows:
...@@ -144,29 +176,47 @@ class Wantzel(object): ...@@ -144,29 +176,47 @@ class Wantzel(object):
if "a" in command: if "a" in command:
note -= 2 note -= 2
#TODO: Gérer les autres champs qui n'ont pas de valeur par défaut #TODO: Gérer les autres champs qui n'ont pas de valeur par défaut
# lang, published, nid, screenshot, title, fetched, seemscite
print("Adding an article by %s: %s" % (user, url))
result = cursor.execute( result = cursor.execute(
"INSERT INTO presse SET url=%s, provenance=%s, cite=%s, note=%s, datec=NOW()", "INSERT INTO presse SET url=%s, provenance=%s, cite=%s, note=%s, datec=NOW()",
(url, user, cite, note) (url, user, cite, note)
) )
self.send_message(channel, messages["merci_nouvel_article"] % user) self.send_message(channel, messages["rp_new_article"] % user)
else: else:
print("Ajout d'un point par %s sur %s" % (rows[0][2], rows[0][0]))
if rows[0][2]!=user: if rows[0][2]!=user:
print("Adding a point by %s on %s" % (user, rows[0][0]))
result = cursor.execute( result = cursor.execute(
"UPDATE presse SET note=note+1 WHERE id=%s", "UPDATE presse SET note=note+1 WHERE id=%s",
(rows[0][0], ) (rows[0][0], )
) )
if (rows[0][1]+1)<3: if (rows[0][1]+1)<3:
self.send_message(channel, messages["merci_article_connu"] % user) self.send_message(channel, messages["rp_known_article"] % user)
else: else:
self.send_message(channel, messages["merci_article_repris"] % user) self.send_message(channel, messages["rp_taken_article"] % user)
def kill(self, user, channel, msg): def kill(self, user, channel, msg):
""" """
Kill an article by removing 100 points to its score. Kill an article by setting its score to -100.
""" """
#TODO: Gérer les droits de cette commande
print("kill command") print("kill command")
pass url = get_url(msg, "kill")
print("url: %s" % url)
if url=="":
return
elif url=="http":
self.send_message(channel, messages["rp_http"] % user)
return
# Looking for such an article in database
cursor = get_cursor()
cursor.execute("SELECT id, note FROM presse WHERE url=%s", (url, ))
rows = cursor.fetchall()
if not rows:
self.send_message(channel, messages["kill_none"] % url)
else:
cursor.execute("UPDATE presse SET note=-100 WHERE id=%s", (rows[0][0], ))
self.send_message(channel, messages["kill_done"] % url)
def stats(self, user, channel, msg): def stats(self, user, channel, msg):
""" """
...@@ -182,7 +232,7 @@ class Wantzel(object): ...@@ -182,7 +232,7 @@ class Wantzel(object):
result = "" result = ""
for note in notes: for note in notes:
notnull = 0 notnull = 0
result = result + " note: %s => " % note result = result + "note>=%s: " % note
for period in periods: for period in periods:
cursor.execute( cursor.execute(
"""SELECT COUNT(id) AS cid FROM presse """SELECT COUNT(id) AS cid FROM presse
...@@ -195,29 +245,14 @@ class Wantzel(object): ...@@ -195,29 +245,14 @@ class Wantzel(object):
if rows[0][0]>0: if rows[0][0]>0:
result = result + "%sj:%s, " % (period, rows[0][0]) result = result + "%sj:%s, " % (period, rows[0][0])
notnull = 1 notnull = 1
somethingatall=1 somethingatall = 1
if notnull: if notnull:
result = result[:-2] + "\n" result = result[:-2] + "\n"
if not somethingatall: if somethingatall==0:
#TODO: Bravo! result = messages["stats_bravo"] % periods[-1]
result = "Bravo!"
self.send_message(channel, result) self.send_message(channel, result)
def quote(self, user, channel, msg):
"""
Record a quote of a VIP during debates.
"""
print("quote command")
pass
def tc(self, user, channel, msg):
"""
Timecode...
"""
print("tc command")
pass
if __name__ == '__main__': if __name__ == '__main__':
wantzel = Wantzel() wantzel = Wantzel()
reactor.run() reactor.run()
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