--- /dev/null
+#!/usr/bin/python
+# -*- coding:utf8 -*-
+
+"""
+Bot qui insulte les gens qui signent mal sur les news.
+
+Codé par 20-100 le 02... ah non le 03/04/12 sur une idée de NeK
+C'est la version 2, parce qu'en utilisant la lib python faite pour,
+c'est quand même plus facile :D
+"""
+
+import nntplib
+import pickle
+import time, re
+import sys
+from commands import getstatusoutput as ex
+
+workingfile="tmpfile.article"
+
+reallypost=False
+if "-reallypost" in sys.argv:
+ reallypost=True
+
+save=False
+if "-save" in sys.argv:
+ save=True
+
+def load_read():
+ # charge le dico des derniers messages lus
+ return pickle.load(open("dicoread.txt"))
+
+def save_read(dicoread):
+ # sauvegarde le dio des derniers messages lus
+ pickle.dump(dicoread,open("dicoread.txt","w"))
+
+
+con=nntplib.NNTP("news.crans.org")
+dicoread=load_read()
+
+newmessages=[]
+dicounread={}
+for group in dicoread.keys():
+ # on récupère le dernier id dans ce groupe
+ _,_,_,last,_=con.group(group)
+ dicounread[group]=int(last)
+ # on rajoute les infos des messages suivants
+ if int(last)>dicoread[group]:
+ bla=con.xover(str(dicoread[group]),last)[1]
+ newmessages+=bla
+
+# on enlève les doubles en filtrant sur le message-id
+nodouble=[]
+for m in newmessages:
+ if not m[4] in [n[4] for n in nodouble]:
+ nodouble.append(m)
+newmessages=nodouble
+
+for (_,subject,poster,date,ident,refs,_,_) in newmessages:
+ messagelines=con.body(ident)[3]
+ if not "-- " in messagelines:
+ # alors il est mal signé
+ # on a besoin des newsgroups sur lesquels il a été posté
+ # et on obéit au Followup-To
+ headers=con.head(ident)[3]
+ ng,fu2="crans.test",None
+ for h in headers:
+ if re.match('Newsgroups',h):
+ ng=h[12:]
+ elif re.match('Followup-To',h):
+ fu2=h[13:]
+ if fu2:
+ ng=fu2
+ "\n".join(messagelines)
+ date=time.strptime(date[:-6],"%a, %d %b %Y %H:%M:%S")
+ date=time.strftime("Le %d/%m/%Y %H:%M",date)
+ f=open("workingfile",'w')
+ f.write("post\n")
+ f.write("From: sign-bot@crans.org\r\n")
+ f.write("Subject: %s\r\n"%(subject))
+ f.write("References: %s %s\r\n"%(refs,ident))
+ f.write("In-Reply-To: %s\r\n"%(ident))
+ f.write("Newsgroups: %s\r\n"%(ng))
+ f.write("Content-Type: text/plain; charset=utf-8\r\n")
+ f.write("Content-Transfer-Encoding: 8bit\r\n\r\n")
+ f.write("%s, %s a écrit :\r\n"%(date,re.sub('<.*>','',poster)))
+ f.write(">"+"\r\n>".join(messagelines))
+ f.write("\r\n\r\nPour signer, c'est\r\n[tiret][tiret][espace][entrée]\r\n[signature]\r\n-- \r\nSign-bot\r\n")
+ f.write(".\r\n")
+ f.write("quit\n")
+ f.close()
+ if ng=="crans.test":
+ if reallypost:
+ out=ex("cat workingfile | nc news.crans.org nntp")
+ else:
+ out=ex("cat workingfile")[1]
+ #print out
+ print subject, poster
+
+
+# On enregistre les messages qu'on a maintenant traité
+if save:
+ save_read(dicounread)
--- /dev/null
+#!/usr/bin/python
+# -*- coding:utf8 -*-
+
+# codé par 20-100 à partir du 02/04/12, sur une idée de NeK
+
+import socket
+import time
+import pickle
+import re
+
+def start():
+ # ouvre une connexion avec le serveur de news et renvoie la socket
+ s=socket.socket()
+ s.connect(("news.crans.org",119))
+ s.recv(4096)
+ return s
+
+def ask(s,something):
+ # effectue une requête et renvoie (execution_code,result)
+ s.send(something+"\n")
+ time.sleep(0.05)
+ t=s.recv(8192)
+ try:
+ firstline,rest=t.split(' ',1)
+ except:
+ print t
+ raise
+ return int(firstline.split()[0]),rest
+
+def get_groups(s):
+ # donne la liste des groupes existants
+ cod,t=ask(s,"list")
+ if cod in range(200,300):
+ l=t.split("\n")[2:-2]
+ return [i.split()[0] for i in l]
+ else:
+ raise KeyboardInterrup("communication error : %s"%(cod))
+
+def load_read():
+ # charge le dico des derniers messages lus
+ return pickle.load(open("dicoread.txt"))
+
+def save_read(dicoread):
+ # sauvegarde le dio des derniers messages lus
+ pickle.dump(dicoread,open("dicoread.txt","w"))
+
+def get_last_message(s,group):
+ # renvoie le dernier message existant dans un groupe
+ cod,t=ask(s,"group %s"%(group))
+ if cod in range(200,300):
+ return int(t.split()[2])
+ else:
+ raise KeyboardInterrup("communication error : %s"%(cod))
+
+def get_all_last(s,groups):
+ # récupère les derniers messages de tous les groupes
+ dicolast={}
+ for g in groups:
+ dicolast[g]=get_last_message(s,g)
+ return dicolast
+
+def get_nouveaux_messages(s,groups,dicoread,dicounread):
+ # crée un itérateurs sur les nouveaux messages
+ # un "nouveau" message c'est un message dont le numéro
+ # est supérieur strict à celui dans dicoread
+ # mais inférieur à celui dans dicounread
+ for g in groups:
+ if not(dicoread.has_key(g)):
+ dicoread[g]=0
+ # il faut lui redire dans quel groupe on est
+ ask(s,"group %s"%(g))
+ for ident in range(dicoread[g]+1,dicounread[g]+1):
+ # on demande les headers du message
+ cod,rest=ask(s,"head %s"%(ident))
+ if cod in range(200,300):
+ mid=re.findall('Message-ID:(.*)',t)[0].strip()
+ ref=False
+ try:
+ ref=re.findall('References:(.*)',t)[0].strip()
+ _,message
+ yield rest
+ else:
+ # bon bah ce massage existe pas, tant pis
+ pass