-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmessage.py
executable file
·160 lines (103 loc) · 4.4 KB
/
message.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#! /usr/bin/python3
# by FvH, released under Apache License v2.0
# either install 'python3-paho-mqtt' or 'pip3 install paho-mqtt'
# CREATE TABLE messages(nr INTEGER PRIMARY KEY, ts DATETIME DEFAULT CURRENT_TIMESTAMP, for_whom text not null, by_whom text not null, what text not null);
# CREATE INDEX for_whom_idx ON messages(for_whom);
import paho.mqtt.client as mqtt
import sqlite3
import threading
import time
import socket
import sys
mqtt_server = 'mqtt.vm.nurd.space' # TODO: hostname of MQTT server
topic_prefix = 'GHBot/' # leave this as is
channels = ['nurdbottest', 'nurds', 'nurdsbofh'] # TODO: channels to respond to
prefix = '!' # !command, will be updated by ghbot
db = 'message.db'
con = sqlite3.connect(db)
cur = con.cursor()
cur.execute('PRAGMA journal_mode=wal')
cur.close()
con.commit()
def announce_commands(client):
target_topic = f'{topic_prefix}to/bot/register'
client.publish(target_topic, 'cmd=message|descr=Leave a message')
def on_message(client, userdata, message):
global prefix
text = message.payload.decode('utf-8')
topic = message.topic[len(topic_prefix):]
if topic == 'from/bot/command' and text == 'register':
announce_commands(client)
return
if topic == 'from/bot/parameter/prefix':
prefix = text
return
if len(text) == 0:
return
parts = topic.split('/')
channel = parts[2] if len(parts) >= 3 else 'nurds' # default channel if can't be deduced
nick = parts[3] if len(parts) >= 4 else 'jemoeder' # default nick if it can't be deduced
if len(parts) >= 4 and parts[3] == 'topic':
return
command = text[1:].split()[0]
if channel in channels or (len(channel) >= 1 and channel[0] == '\\'):
response_topic = f'{topic_prefix}to/irc/{channel}/privmsg'
# check for stored messages for this nick
try:
if '!' in nick:
nick = nick[0:nick.find('!')]
nick = nick.lower()
nick_topic = f'{topic_prefix}to/irc-person/{nick}'
print(f'Check for messages for {nick}')
q = 'SELECT nr, ts, by_whom, what FROM messages WHERE for_whom=?'
cur = con.cursor()
cur.execute(q, (nick, ))
for row in cur.fetchall():
nr = row[0]
by_whom = row[2]
ts = row[1]
what = row[3]
print(f'Sending message by {by_whom} to {nick}')
client.publish(nick_topic, f'{by_whom}@{ts}: {what}')
if '!' in by_whom:
by_whom = by_whom[0:by_whom.find('!')]
by_whom_topic = f'{topic_prefix}to/irc-person/{by_whom}'
client.publish(by_whom_topic, f'Message for {nick} from {ts} delivered ({what})')
cur2 = con.cursor()
cur2.execute('DELETE FROM messages WHERE nr=?', (nr,))
cur2.close()
cur.close()
con.commit()
except Exception as e:
print(f'exception: {e}, line number: {e.__traceback__.tb_lineno}')
# process any command
if command == 'message':
try:
tokens = text.split()
if len(tokens) < 3:
return
user = tokens[1].lower()
cur = con.cursor()
cur.execute('INSERT INTO messages(by_whom, for_whom, what) VALUES(?, ?, ?)', (nick, user, text,))
cur.close()
con.commit()
client.publish(response_topic, f'Message for {user} stored')
except Exception as e:
client.publish(response_topic, f'Message for {user} NOT stored: {e}, line number: {e.__traceback__.tb_lineno}')
def on_connect(client, userdata, flags, rc):
client.subscribe(f'{topic_prefix}from/irc/#')
client.subscribe(f'{topic_prefix}from/bot/command')
def announce_thread(client):
while True:
try:
announce_commands(client)
time.sleep(4.1)
except Exception as e:
print(f'Failed to announce: {e}')
client = mqtt.Client(f'{socket.gethostname()}_{sys.argv[0]}', clean_session=False)
client.on_message = on_message
client.on_connect = on_connect
client.connect(mqtt_server, port=1883, keepalive=4, bind_address="")
t = threading.Thread(target=announce_thread, args=(client,))
t.start()
client.loop_forever()