-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ircbot: add shorturl plugin #94
Changes from 3 commits
83b8d95
c066279
477f530
10ab80e
1ebed71
2c617b0
0cc96ea
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
"""Control ocfweb shorturls through ircbot.""" | ||
from ircbot import db | ||
|
||
KEYWORDS = {'add', 'delete', 'rename', 'replace'} | ||
|
||
|
||
def register(bot): | ||
# [!-~] is all printable ascii except spaces | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we want shorturls to be able to contain There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ...Well now this won't allow hyphens or underscores. Methinks those are still useful characters. |
||
bot.listen(r'^!shorturl ([\w/]+)', show) | ||
bot.listen(r'^!shorturl add ([\w/]+) (.+)$', add) | ||
bot.listen(r'^!shorturl delete ([\w/]+)$', delete) | ||
bot.listen(r'^!shorturl rename ([\w/]+) ([\w/]+)$', rename) | ||
bot.listen(r'^!shorturl replace ([\w/]+) (.+)$', replace) | ||
|
||
|
||
def list(bot): | ||
"""List all shorturls for shorturls help page.""" | ||
|
||
with db.cursor(password=bot.mysql_password) as c: | ||
c.execute('SELECT slug, target FROM shorturls ORDER BY slug') | ||
|
||
for entry in c.fetchall(): | ||
yield entry['slug'], entry['target'] | ||
|
||
|
||
def retrieve(bot, slug): | ||
"""Reusable function to retrieve a shorturl by slug from the DB.""" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this need the |
||
|
||
with db.cursor(password=bot.mysql_password) as c: | ||
c.execute( | ||
'SELECT target FROM shorturls WHERE slug = %s', | ||
(slug,), | ||
) | ||
target = c.fetchone() | ||
|
||
return target['target'] if target else None | ||
|
||
|
||
def show(bot, msg): | ||
"""Return a shorturl by slug.""" | ||
|
||
slug = msg.match.group(1) | ||
|
||
# special case these so show doesn't trigger on add/delete | ||
# while still letting the trigger appear anywhere in the msg | ||
if slug in KEYWORDS: | ||
return | ||
|
||
target = retrieve(bot, slug) | ||
if not target: | ||
msg.respond('shorturl `{}` does not exist.'.format(slug)) | ||
else: | ||
msg.respond(target['target'], ping=False) | ||
|
||
|
||
def add(bot, msg): | ||
"""Add a new shorturl.""" | ||
|
||
slug = msg.match.group(1) | ||
target = msg.match.group(2) | ||
|
||
if slug in KEYWORDS: | ||
msg.respond('`{}` is a reserved keyword.'.format(slug)) | ||
return | ||
|
||
if len(slug) > 255: | ||
msg.respond('shorturl slugs must be <= 255 characters') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this unfairly discriminates against all of those massive facebook URLs with a million query parameters! how else will Big ZUCC be able to do the machine learnings to see how people are clicking the links? /s There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this only limits the size of the slug itself, not the target |
||
return | ||
|
||
with db.cursor(password=bot.mysql_password) as c: | ||
|
||
c.execute('SELECT * FROM shorturls WHERE slug = %s', (slug,)) | ||
result = c.fetchone() | ||
if result is not None: | ||
msg.respond( | ||
'shorturl `{}` already exists as {}'.format( | ||
result['slug'], | ||
result['target'], | ||
), | ||
) | ||
else: | ||
c.execute( | ||
'INSERT INTO shorturls (slug, target) VALUES (%s, %s)', | ||
(slug, target), | ||
) | ||
msg.respond('shorturl added as `{}`'.format(slug)) | ||
|
||
|
||
def delete(bot, msg): | ||
"""Delete a shorturl.""" | ||
|
||
slug = msg.match.group(1) | ||
with db.cursor(password=bot.mysql_password) as c: | ||
c.execute( | ||
'DELETE FROM shorturls WHERE slug = %s', | ||
(slug,), | ||
) | ||
msg.respond('shorturl `{}` has been deleted.'.format(slug)) | ||
|
||
|
||
def rename(bot, msg): | ||
"""Rename a shorturl.""" | ||
|
||
old_slug = msg.match.group(1) | ||
new_slug = msg.match.group(2) | ||
|
||
if new_slug in KEYWORDS: | ||
msg.respond('`{}` is a reserved keyword.'.format(new_slug)) | ||
return | ||
|
||
with db.cursor(password=bot.mysql_password) as c: | ||
c.execute( | ||
'UPDATE shorturls SET slug = %s WHERE slug = %s', | ||
(new_slug, old_slug), | ||
) | ||
msg.respond('shorturl `{}` has been renamed to `{}`'.format(old_slug, new_slug)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what happens when the old slug does not exist? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nothing, the where clause doesn't match anything so it's a no-op |
||
|
||
|
||
def replace(bot, msg): | ||
"""Replace the target of a shorturl slug.""" | ||
|
||
slug = msg.match.group(1) | ||
new_target = msg.match.group(2) | ||
|
||
with db.cursor(password=bot.mysql_password) as c: | ||
c.execute( | ||
'UPDATE shorturls SET target = %s WHERE slug = %s', | ||
(new_target, slug), | ||
) | ||
msg.respond('shorturl `{}` updated'.format(slug)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. likewise, what happens when the slug does not exist? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ibid |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
<!doctype html> | ||
<html lang="en"> | ||
<head> | ||
<title>ocf shorturls</title> | ||
<style> | ||
code { background-color: #eee; padding: 3px; } | ||
.slug { font-weight: bold } | ||
.link {} | ||
</style> | ||
</head> | ||
<body> | ||
<h1>shorturls available at ocf</h1> | ||
<hr /> | ||
|
||
<p>Available shorturls are:</p> | ||
<ul> | ||
{% for slug, target in shorturls %} | ||
<li> | ||
<p><span class="slug">{{slug}}</span>: <span class="link"><a href="{{ target }}">{{ target }}</a></span></p> | ||
</li> | ||
{% endfor %} | ||
</ul> | ||
</body> | ||
</html> | ||
{# vim: ft=jinja | ||
#} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we plan to have any authentication before deleting shorturls?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If possible, I would try to limit deletion to ops or half-ops (do we even have half-ops?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same with replacement and similar non-adding commands