home · contact · privacy
Add some whitespace to code for better readability.
[plomlombot-irc.git] / plomlombot.py
1 import socket
2 import datetime 
3 import select
4 import time
5 import re
6 import urllib.request
7 import html
8
9 servername = ""
10 timeout = 480
11 username = "plomlombot"
12 nickname = username
13 channel = "#zrolaps"
14
15 class IO:
16
17     def __init__(self, server, port):
18         self.socket = socket.socket()
19         self.socket.connect((server, port))
20         self.socket.setblocking(0)
21         self.line_buffer = []
22         self.rune_buffer = ""
23         self.last_pong = time.time()
24
25     def _pingtest(self):
26         if self.last_pong + timeout < time.time():
27             raise RuntimeError("server not answering")
28         self.send_line("PING " + nickname + " " + servername)
29
30     def send_line(self, msg):
31         msg = msg.replace("\r", " ")
32         msg = msg.replace("\n", " ")
33         if len(msg.encode("utf-8")) > 510:
34             print("NOT SENT LINE TO SERVER (too long): " + msg)
35         print("LINE TO SERVER: "
36             + str(datetime.datetime.now()) + ": " + msg)
37         msg = msg + "\r\n"
38         msg_len = len(msg)
39         total_sent_len = 0
40         while total_sent_len < msg_len:
41             sent_len = self.socket.send(bytes(msg[total_sent_len:], "UTF-8"))
42             if sent_len == 0:
43                 raise RuntimeError("socket connection broken")
44             total_sent_len += sent_len
45
46     def recv_line_wrapped(self):
47         if len(self.line_buffer) > 0:
48             return self.line_buffer.pop(0)
49         while True:
50             ready = select.select([self.socket], [], [], int(timeout / 2))
51             if not ready[0]:
52                 self._pingtest()
53                 return None
54             self.last_pong = time.time()
55             received_runes = self.socket.recv(1024).decode("UTF-8")
56             if len(received_runes) == 0:
57                 raise RuntimeError("socket connection broken")
58             self.rune_buffer += received_runes 
59             lines_split = str.split(self.rune_buffer, "\r\n")
60             self.line_buffer += lines_split[:-1]
61             self.rune_buffer = lines_split[-1]
62             if len(self.line_buffer) > 0:
63                 return self.line_buffer.pop(0)
64
65     def recv_line(self):
66         line = self.recv_line_wrapped()
67         if line:
68             print("LINE FROM SERVER " + str(datetime.datetime.now()) + ": " +
69             line)
70         return line
71
72 io = IO("irc.freenode.net", 6667)
73 io.send_line("NICK " + nickname)
74 io.send_line("USER " + username + " 0 * : ")
75 io.send_line("JOIN " + channel)
76 servername = io.recv_line().split(" ")[0][1:]
77 while 1:
78     line = io.recv_line()
79     if not line:
80         continue
81     tokens = line.split(" ")
82     if len(tokens) > 1:
83         if tokens[1] == "PRIVMSG":
84             sender = ""
85             for rune in tokens[0]:
86                 if rune == "!":
87                     break
88                 if rune != ":":
89                     sender += rune
90             receiver = ""
91             for rune in tokens[2]:
92                 if rune == "!":
93                     break
94                 if rune != ":":
95                     receiver += rune
96             target = sender
97             if receiver != nickname:
98                 target = receiver
99             msg = str.join(" ", tokens[3:])[1:]
100             matches = re.findall("(https?://[^\s]+)", msg)
101             for i in range(len(matches)):
102                 url = matches[i]
103                 webpage = urllib.request.urlopen(url)
104                 charset = webpage.info().get_content_charset()
105                 content = webpage.read().decode(charset)
106                 title = str(content).split('<title>')[1].split('</title>')[0]
107                 title = html.unescape(title)
108                 io.send_line("PRIVMSG "
109                     + target + " :page title for url: " + title)
110         if tokens[0] == "PING":
111             io.send_line("PONG " + tokens[1])