Skip to content
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

Merged
merged 7 commits into from
Feb 28, 2019
Merged
Show file tree
Hide file tree
Changes from 5 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
11 changes: 7 additions & 4 deletions ircbot/plugin/help.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
def register(bot):
threading.Thread(target=help_server, args=(bot,), daemon=True).start()
bot.listen(r'^help$', help, require_mention=True)
bot.listen(r'^macros$', help_macro, require_mention=True)
bot.listen(r'^macros?$', help_macro, require_mention=True)


def help(bot, msg):
Expand Down Expand Up @@ -39,6 +39,11 @@ def render_response(self, template, **context):
self.end_headers()
self.wfile.write(rendered)

def render_404(self):
self.send_response(404, 'File not found')
self.end_headers()
self.wfile.write(b'404 File not found')

def do_GET(self):
if self.path == '/':
plugins = collections.defaultdict(set)
Expand All @@ -55,9 +60,7 @@ def do_GET(self):
macros=bot.plugins['macros'].list(bot),
)
else:
self.send_response(404, 'File not found')
self.end_headers()
self.wfile.write(b'404 File not found')
self.render_404()

return RequestHandler

Expand Down
120 changes: 120 additions & 0 deletions ircbot/plugin/shorturls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
"""Control ocfweb shorturls through ircbot."""
from ocflib.misc.shorturls import get_connection as shorturl_db

KEYWORDS = {'add', 'delete', 'rename', 'replace'}


def register(bot):
# [!-~] is all printable ascii except spaces
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want shorturls to be able to contain ?, &, or =?

Copy link
Member

@kpengboy kpengboy Jan 30, 2019

Choose a reason for hiding this comment

The 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.
(Also I think you need to update the comment)

bot.listen(r'^!shorturl ([\w/]+)', show)
bot.listen(r'^!shorturl add ([\w/]+) (.+)$', add, require_privileged_oper=True)
bot.listen(r'^!shorturl delete ([\w/]+)$', delete, require_privileged_oper=True)
bot.listen(r'^!shorturl rename ([\w/]+) ([\w/]+)$', rename, require_privileged_oper=True)
bot.listen(r'^!shorturl replace ([\w/]+) (.+)$', replace, require_privileged_oper=True)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace and rename aren't necessary IMO, if we want to change the shorturls we should just delete and re-add



def retrieve(bot, slug):
"""Reusable function to retrieve a shorturl by slug from the DB."""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need the bot param?


with shorturl_db() as c:
c.execute(
'SELECT target FROM shorturls_public 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, 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')
Copy link
Member

Choose a reason for hiding this comment

The 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

Copy link
Member Author

Choose a reason for hiding this comment

The 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 shorturl_db(user='ocfircbot', 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 shorturl_db(user='ocfircbot', 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 shorturl_db(user='ocfircbot', 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))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happens when the old slug does not exist?

Copy link
Member Author

Choose a reason for hiding this comment

The 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 shorturl_db(user='ocfircbot', 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))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

likewise, what happens when the slug does not exist?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ibid