tree checksum vpatch file split hunks

all signers: lobbes

antecedents:

press order:

logbot_command_router_python_genesislobbes

patch:

-
+ F437341526F6E4AF91BC5E137DEC97530D071778C4E682063D0ABCB51881793AAB75B1720B090D00B752F15620E47220952A662E0F10EE67A4054FDE9048FB31
commands/bot_help.py
(0 . 0)(1 . 7)
5 import postgres_interfacing
6
7 class bot_help():
8
9 def reply(self, target, source, command_arguments):
10 my_postgres_interfacing = postgres_interfacing.postgres_interfacing()
11 my_postgres_interfacing.irc_reply(target, source, "Default help. Known commands: help, ping")
-
+ F8ACA02E28996A586F535EED5DE9F4533B8B2910762F524459F6FAE6FB3F8F7540DB5F2C809C1C07167A95B33F6F3F85589AF99182E2D2BF93F964DE169DD4C0
commands/__init__.py
(0 . 0)(1 . 1)
16
-
+ 8C388A0AAD581C48387FC3A938FED1AECE5D6630D1FD65C98B960E56290E12C31CB5041E5D8A2ADF0C1260B72CC0ED3A4B022B605C3DD29E360E251AE0CB86CC
commands/ping_pong.py
(0 . 0)(1 . 11)
21 import postgres_interfacing
22
23 class ping_pong():
24
25 def reply(self, target, source, command_arguments):
26 my_postgres_interfacing = postgres_interfacing.postgres_interfacing()
27 if command_arguments:
28 reply_string = "pong. Here's your arguments back: %s" % command_arguments
29 my_postgres_interfacing.irc_reply(target, source, reply_string)
30 else:
31 my_postgres_interfacing.irc_reply(target, source, "pong")
-
+ 678E7A73F2B948ABF48758FB45E9971F58FCA12FB4C2BB4E6A3B44D10CE01A13FEEB474DAE8EB6C67A29AA3799112C11ABBE94930EE76E16AD555C860CE355CE
__init__.py
(0 . 0)(1 . 1)
36 from main import main
-
+ DA9C78CDBA2E22483C539BDA2F68E8965814D0452B09B74E28C83B85E077AA594EFB248E0C0175AFC855C7D594049F2C8C82DEE1A1CE465DB361C8366FF80618
INSTALL
(0 . 0)(1 . 15)
41 Install the following via your preferred method:
42
43 logbot-genesis or logbot-multiple-channels-corrected (http://btcbase.org/patches?patchset=bot&search=)
44 psycopg2 (a PostgreSQL adapter for Python: http://initd.org/psycopg/)
45
46 Press logbot_command_router_python via your preferred V:
47
48 mkdir -p ~/src/logbot_command_router_python
49 cd ~/src/logbot_command_router_python
50
51 mkdir .wot
52 cd .wot && wget http://www.lobbesblog.com/lobbes.asc && cd ..
53
54 v.pl init http://www.lobbesblog.com/src/logbot_command_router_python
55 v.pl press logbot_command_router_python logbot_command_router_python_genesis.vpatch
-
+ E5B5BE2D2DB8E1309B0D34E87700B638915336E6B63413F90C15576A2B60BEFA4C9FC0F1D837B4E937032A67E95265FBE644756E44843134E65A3B1220CB0579
knobs/config.py
(0 . 0)(1 . 25)
60 """
61 Set your postgres connection info
62 NOTE: If your Postgres socket is located somewhere other than '/var/run/postgresql/',
63 you will have to specify your host in the postgres connection string . E.g. 'host=/tmp/'
64 """
65 postgres = {'connection_string': 'dbname=your_postgres_db user=your_postgres_user',
66 'channel': 'log_new_message'}
67 """
68 Set your bot name and command prefix
69 """
70 bot = {'bot_name': 'your_bot',
71 'bot_command_prefix': '!your_command_prefix'}
72 """
73 Set this to True if you want main.py to pass ALL irc messages to router.py
74 instead of just messages intended to be commands (i.e. messages starting with bot_command_prefix).
75 This could be useful if, e.g. you are making an archive bot or a log quoter.
76 """
77 route_all_notifications = False
78 """
79 Set your list of irc nicks to ignore
80 Irc messages originating from a nick on this list will be 'ignored' by main.py
81 (i.e. those messages will not be processed nor commands routed)
82 This could be useful if, e.g. you are running many bots in the same channel and don't want them talking to each other.
83 """
84 ignore_list = ('examplebot','gavinandresen')
-
+ F8ACA02E28996A586F535EED5DE9F4533B8B2910762F524459F6FAE6FB3F8F7540DB5F2C809C1C07167A95B33F6F3F85589AF99182E2D2BF93F964DE169DD4C0
knobs/__init__.py
(0 . 0)(1 . 1)
89
-
+ 77C9615F3F5C06B35198259CE46F3C7447DDB952A196DA8002AA874124C4E5391B1C46AD0EEE62902234996AFBF5771F677C1EDC70BD5DC0355C11133704ACC1
knobs/router.py
(0 . 0)(1 . 45)
94 """
95 Import your custom command modules here
96 (alternatively, you -could- put all your command handling scripts in the
97 router() class below, but that could prove messy over time)
98 """
99 from commands import ping_pong, bot_help
100
101 class router:
102 """
103 Each function in this class beginning with 'cmd_' represents a command for logbot.
104
105 Functions intending to be used as callable bot commands MUST use the following format:
106 'cmd_[command to be issued from irc](self, target, source, command_arguments)'
107 source = *irc nick* that issued command
108 target = *where* the irc nick issued the command
109 command_arguments = string representing everything *to the right of* the command issued (to be parsed or ignored as you wish)
110
111 Example:
112 Say you have a knobs.config.bot_command_prefix value of '!G'
113 Someone issuing '!Gping randomgibberish' in #example-irc-channel-where-logbot-is-sitting
114 will trigger main.py to call cmd_ping(), passing ' randomgibberish' to command_arguments.
115
116 In the example above, cmd_ping() just ignores the ' randomgibberish' and simply passes the target and source data to ping_pong.pong() function.
117 However, you could instead choose to parse the 'randomgibberish' and do things with it.
118
119 Hint: You have two easy ways to send command responses back to a target irc channel or nick:
120 1) Use postgres_interfacing.send_to_outbox(target, payload)
121 Directly inserts a record into the 'outbox' table (this is the 'raw' function)
122 2) Use postgres_interfacing.irc_reply(self, target, source, payload)
123 Target and source will be validated before sending data to the 'outbox' table (recommended in most cases)
124 """
125 def cmd_ping(self, target, source, command_arguments):
126 my_pingpong = ping_pong.ping_pong()
127 my_pingpong.reply(target, source, command_arguments)
128
129 def cmd_help(self, target, source, command_arguments):
130 my_bot_help = bot_help.bot_help()
131 my_bot_help.reply(target, source, command_arguments)
132
133 def passive(self, target, source, message):
134 """
135 If knobs.config.route_all_notifications is set to 'True', then main.py will route ALL 'non-command' messages through this function.
136 Useful for, e.g. log-quoters and archive bots
137 """
138 pass
-
+ EF0185BD3B618AC6C82EECA7AEE17E7DFB5F1863330C9BF80BD68880A69BA1F285F4E51AC9E01438481F52541B8AD01C05F5371809925365BAF77ED2FECC5721
main.py
(0 . 0)(1 . 73)
143 #!/usr/bin/env python2
144 import select
145 import psycopg2
146 import psycopg2.extensions
147 from knobs import router
148 import postgres_interfacing
149
150 class main():
151 #LISTEN to postgres_channel for postgres-payload and parse for commands intended for bot, routing it to the proper submodule.
152 #For use with logbot-genesis or logbot-multiple-channels-corrected on a LOCAL postgres server
153
154 def __init__(self):
155 self.my_router = router.router()
156 self.my_interface = postgres_interfacing.postgres_interfacing()
157
158 def parse_message(self, message):
159 #parse irc message for valid command-calling syntax and return extracted command and arguments
160 bot_command_prefix = self.my_interface.bot_command_prefix
161 bot_command_prefix_len = len(bot_command_prefix)
162 if message[:bot_command_prefix_len] in bot_command_prefix:
163 command_start_pos = bot_command_prefix_len + (len(message[bot_command_prefix_len:]) - len(message[bot_command_prefix_len:].lstrip()))
164 if message[command_start_pos:].find(" ") > -1:
165 command_end_pos = command_start_pos + message[command_start_pos:].find(" ")
166 command = message[command_start_pos:command_end_pos]
167 command_arguments = message[command_end_pos:]
168 else:
169 command = message[command_start_pos:]
170 command_arguments = ""
171 return command, command_arguments
172
173 def send_to_command_router(self, target, source, command, command_arguments):
174 #do stuff with valid commands
175 command_function = "cmd_%s" % command
176 try:
177 route_command = getattr(self.my_router, command_function)(target, source, command_arguments)
178 except AttributeError:
179 pass
180
181 def listen_for_notifications(self):
182 #Main Loop ===================
183 #Execute a LISTEN on the 'log_new_message' channel on local postgres server.
184 #If NOTIFY is recieved, feed the payload (which corresponds to an id in the 'log' table) into fetch_irc_message() to return the message.
185 #Parse message and handle as configured in knobs and commands
186 conn = psycopg2.connect(self.my_interface.connection_string)
187 conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
188 cur = conn.cursor()
189 cur.execute(self.my_interface.postgres_listen_string)
190 print "Waiting for notifications on postgres channel '%s'" % self.my_interface.postgres_channel
191 while 1:
192 if select.select([conn],[],[],5) == ([],[],[]):
193 print "Timeout"
194 else:
195 conn.poll()
196 while conn.notifies:
197 notify = conn.notifies.pop(0)
198 print "Got NOTIFY:", notify.pid, notify.channel, notify.payload
199 target, source, message = self.my_interface.fetch_irc_message(notify.payload)
200 print "Message: %s" % message
201 if source not in self.my_interface.ignore_list:
202 if self.parse_message(message):
203 command, command_arguments = self.parse_message(message)
204 print "Attempting to route command '%s' with arguments '%s'..." % (command, command_arguments)
205 self.send_to_command_router(target, source, command, command_arguments)
206 elif self.my_interface.route_all_notifications == True:
207 print "Routing non-command message: '%s'" % message
208 self.my_router.passive(target, source, message)
209 else:
210 print "Ignoring nick '%s'" % source
211
212 if __name__ == "__main__":
213 print "running"
214 my_connection = main()
215 my_connection.listen_for_notifications()
-
+ 13BDA7A95EDFE0BF6BDBC56629A598B7D1AFA21AA96A49396CE49BDDB4DC10E5017BB78A098C7873950465044030D75440C476D5C1A14F996C34FB49721DE26B
postgres_interfacing.py
(0 . 0)(1 . 45)
220 import select
221 import psycopg2
222 import psycopg2.extensions
223 from knobs import config
224
225 class postgres_interfacing():
226
227 def __init__(self):
228 self.connection_string = config.postgres['connection_string']
229 self.postgres_channel = config.postgres['channel']
230 self.postgres_listen_string = "LISTEN %s;" % self.postgres_channel
231 self.bot_command_prefix = config.bot['bot_command_prefix']
232 self.bot_name = config.bot['bot_name']
233 self.route_all_notifications = config.route_all_notifications
234 self.ignore_list = config.ignore_list
235
236 def send_to_outbox(self, target, payload):
237 #Insert a target and message into the 'outbox' table on local postgres server
238 conn = psycopg2.connect(self.connection_string)
239 cur = conn.cursor()
240 cur.execute("INSERT INTO outbox(target, message) VALUES(%s,%s)", (target, payload))
241 conn.commit()
242 cur.close()
243 conn.close()
244
245 def irc_reply(self, target, source, payload):
246 if source != self.bot_name:
247 #make sure bot doesn't talk to itself
248 if target == self.bot_name:
249 #is the target this bot
250 self.send_to_outbox(source, payload)
251 elif target[:1] == '#':
252 #is the target a channel
253 self.send_to_outbox(target, payload)
254
255 def fetch_irc_message(self, log_id):
256 #Fetch the irc message in the 'log' table based off of the log id
257 conn = psycopg2.connect(self.connection_string)
258 cur = conn.cursor()
259 cur.execute("SELECT target, source, message FROM log WHERE id = %s;", (log_id,))
260 row = cur.fetchone()
261 target, source, message = row[0], row[1], row[2]
262 return target, source, message
263 cur.close()
264 conn.close()
-
+ 380E59A124DBB4C6B4DB0BC8AD7F5518522D1CEE432D84781A67142302C1C157B25545421C189BE1A63922C94CF15137F6B69B8C28B2CDF691F81E190FC4043A
README
(0 . 0)(1 . 15)
269 HOW TO USE:
270
271 Bits designed to be customized to your needs:
272 knobs/config.py << Edit you postgres db connection info, bot command prefix, etc.
273 knobs/router.py << The central command router. Write or pull in your custom commands here.
274 commands/* << A directory to house command scripts that you can import into router.py
275
276 To run:
277 Configure your bits mentioned above
278 Start your local postgres server and your instance of logbot or logbot-multiple-channels-corrected
279 ./main.py
280
281 CAVEATS:
282
283 Designed to communicate with a LOCAL Postgres server only, not remote. (Feel free to extend this to add that capability, however)