Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# zlog-sql
MySQL/SQLite logging plugin for ZNC IRC bouncer written in Python 3

## Update 21/04/2022

I added the ability to parse port in database connection string specified as this module argument

## Features
* Supports MySQL, PostgreSQL and SQLite databases.
* Asynchronous database writes on separate thread. Guarantees that ZNC won't hang during SQL connection timeout.
Expand All @@ -25,14 +29,14 @@ MySQL gives great compression ratio and is easily searchable. SQLite database do
### MySQL
For MySQL, set module argument matching following format:
```
mysql://username:password@localhost/database_name
mysql://username:password@localhost:port/database_name
```
**Important:** you need [`PyMySQL`](https://github.com/PyMySQL/PyMySQL) pip package for MySQL logging. Install it with `pip3 install PyMySQL` command.

### PostgreSQL
For PostgreSQL, set module argument matching following format:
```
postgres://username:password@localhost/database_name
postgres://username:password@localhost:port/database_name
```
**Important:** you need [`psycopg2`](https://github.com/psycopg/psycopg2) pip package for PostgreSQL logging. Install it with `pip3 install psycopg2` command.

Expand Down
40 changes: 28 additions & 12 deletions zlog_sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ class zlog_sql(znc.Module):
wiki_page = 'ZLog_SQL'

has_args = True
args_help_text = ('Connection string in format: mysql://user:pass@host/database_name'
' or postgres://user:pass@host/database_name'
args_help_text = ('Connection string in format: mysql://user:pass@host:port/database_name'
' or postgres://user:pass@host:port/database_name'
' or sqlite://path/to/db.sqlite')

log_queue = multiprocessing.SimpleQueue()
Expand Down Expand Up @@ -357,19 +357,35 @@ def parse_args(self, args):
else:
return SQLiteDatabase({'database': match.group(1)})

match = re.search('^\s*mysql://(.+?):(.+?)@(.+?)/(.+)\s*$', args)
match = re.search('^\s*mysql://(.+?):(.+?)@(.+?)(?::(.*))?/(.+)\s*$', args)
if match:
parsedPort = match.group(4)
return MySQLDatabase({'host': match.group(3),
'user': match.group(1),
'passwd': match.group(2),
'db': match.group(4)})

match = re.search('^\s*postgres://(.+?):(.+?)@(.+?)/(.+)\s*$', args)
'port': int(parsedPort),
'user': match.group(1),
'passwd': match.group(2),
'db': match.group(5)}
) if parsedPort != None else MySQLDatabase({'host': match.group(3),
'user': match.group(1),
'passwd': match.group(2),
'db': match.group(5)}
)

match = re.search('^\s*postgres://(.+?):(.+?)@(.+?)(?::(.*))?/(.+)\s*$', args)
if match:
return PostgresDatabase({'host': match.group(3),
'user': match.group(1),
'password': match.group(2),
'database': match.group(4)})
parsedPort = match.group(4)
return PostgresDatabase({
'host': match.group(3),
'port': int(parsedPort),
'user': match.group(1),
'password': match.group(2),
'database': match.group(5)
}) if parsedPort != None else PostgresDatabase({
'host': match.group(3),
'user': match.group(1),
'password': match.group(2),
'database': match.group(5)
})

raise Exception('Unrecognized connection string. Check the documentation.')

Expand Down