Script: url_olde.py

Display when and where a URI was first posted.
Author: yeled — Version: 0.8 — License: GPL-3.0-or-later
For WeeChat ≥ 0.4.0, requires: sqlite.
Tags: url, py3
Added: 2016-10-30 — Updated: 2021-05-11

Download GitHub Repository

  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
# -*- coding: utf-8 -*-
"""
database init code from https://weechat.org/scripts/source/triggerreply.py.html
regex is from http://stackoverflow.com/questions/520031/whats-the-cleanest-way-to-extract-urls-from-a-string-using-python

TODO
----
 - set a preference value for ignoring:
  - nicks
 - purge sql rows after an age range (or fixed size)
"""

SCRIPT_NAME = "url_olde"
SCRIPT_AUTHOR = "Charlie Allom <charlie@evilforbeginners.com>"
SCRIPT_VERSION = "0.8"
SCRIPT_LICENSE = "GPL3"
SCRIPT_DESC = "tells you how long ago a URL was first posted and by whom, for bragging rights."

try:
    import weechat as w
    import sqlite3
    import time
    import re
    from urllib.parse import urldefrag
    IMPORT_ERR = 0
except ImportError:
    IMPORT_ERR = 1
import os

# plugins.var.python.url_olde.ignore_channel
url_olde_settings_default = {
    'ignored_channels': ('chanmon', 'comma separated list of buffers you want ignored. eg. freenode.#channelname')
}
url_olde_settings = {}


def create_db():
    """ create the sqlite database and insert a test URI as id 1 """
    tmpcon = sqlite3.connect(DBFILE)
    cur = tmpcon.cursor()
    cur.execute("CREATE TABLE urls(id INTEGER PRIMARY KEY, uri VARCHAR, date INTEGER, nick VARCHAR, channel VARCHAR);")
    cur.execute("INSERT INTO urls(uri, date, nick, channel) VALUES ('test.com',1,'donald_trump','hello.#world');")
    tmpcon.commit()
    cur.close()


def search_urls_cb(data, buffer, date, tags, displayed, highlight, prefix, message):
    """ searching for the url function
    message is the line that matched '://'
    buffer needs buffer_get_string for the short name
    prefix is nick
    """
    database = sqlite3.connect(DBFILE)
    database.text_factory = str
    cursor = database.cursor()
    nick = prefix
    full_uri = re.findall(r'(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:/[^\s]*)?', message)
    channel = w.buffer_get_string(buffer, 'name')  # current channel.
    # w.prnt(w.current_buffer(), 'full_uri: %s ' % (full_uri)) # debug
    for olde in full_uri:  # iterate over each URI we get in the list from full_uri regex
        if '/#/' in olde:  # run this routine on rails style apps
            url = olde
            uri = url.rstrip("/)")  # strip the final / and lesser-seen )
            new_entry = []  # create an ordered list of the following values we want to INSERT -> sql later on
            new_entry.append(uri)
            new_entry.append(time.time())
            new_entry.append(nick)
            new_entry.append(channel)
            # w.prnt(w.current_buffer(), 'uri: %s ' % (uri)) # debug
            cursor.execute("SELECT date,uri,nick,channel from urls WHERE uri = ?", (uri,))
            result = cursor.fetchone()
            if channel in str(url_olde_settings['ignored_channels']):
                # w.prnt(w.current_buffer(), 'ignoring %s due to ignored_channels = %s' % (uri, str(url_olde_settings['ignored_channels'])))
                return w.WEECHAT_RC_OK
            if result is None:
                """ a new URL is seen! """
                # w.command(buffer, "/notice %s"  % (new_entry))  # debug
                cursor.execute("INSERT INTO urls(uri, date, nick, channel) VALUES (?,?,?,?)", new_entry)
                database.commit()
            else:
                """ we've got a match from sqlite """
                date, uri, nick, channel = result
                timestamp = time.strftime('%Y-%m-%d %H:%M', time.localtime(date))  # convert it to YYYY-MM-DD
                # w.command(buffer, "/notice DING %s"  % str(result)) # debug
                w.prnt_date_tags(buffer, 0, 'no_log,notify_none', 'olde!! already posted by %s in %s on %s' % (nick, channel, timestamp))
        else:  # strip anchors
            url, fragment = urldefrag(olde)
            uri = url.rstrip("/)")  # strip the final / and lesser-seen )
            new_entry = []  # create an ordered list of the following values we want to INSERT -> sql later on
            new_entry.append(uri)
            new_entry.append(time.time())
            new_entry.append(nick)
            new_entry.append(channel)
            # w.prnt(w.current_buffer(), 'uri: %s ' % (uri)) # debug
            cursor.execute("SELECT date,uri,nick,channel from urls WHERE uri = ?", (uri,))
            result = cursor.fetchone()
            if channel in str(url_olde_settings['ignored_channels']):
                # w.prnt(w.current_buffer(), 'ignoring %s due to ignored_channels = %s' % (uri, str(url_olde_settings['ignored_channels'])))
                return w.WEECHAT_RC_OK
            if result is None:
                """ a new URL is seen! """
                # w.command(buffer, "/notice %s"  % (new_entry))  # debug
                cursor.execute("INSERT INTO urls(uri, date, nick, channel) VALUES (?,?,?,?)", new_entry)
                database.commit()
            else:
                """ we've got a match from sqlite """
                date, uri, nick, channel = result
                timestamp = time.strftime('%Y-%m-%d %H:%M', time.localtime(date))  # convert it to YYYY-MM-DD
                # w.command(buffer, "/notice DING %s"  % str(result)) # debug
                w.prnt_date_tags(buffer, 0, 'no_log,notify_none', 'olde!! already posted by %s in %s on %s' % (nick, channel, timestamp))
    return w.WEECHAT_RC_OK


def url_olde_load_config():
    global url_olde_settings_default, url_olde_settings
    version = w.info_get('version_number', '') or 0
    for option, value in url_olde_settings_default.items():
        if w.config_is_set_plugin(option):
            url_olde_settings[option] = w.config_get_plugin(option)
        else:
            w.config_set_plugin(option, value[0])
            url_olde_settings[option] = value[0]
        if int(version) >= 0x00030500:
            w.config_set_desc_plugin(option, value[1])


def url_olde_config_cb(data, option, value):
    """Called each time an option is changed."""
    url_olde_load_config()
    return w.WEECHAT_RC_OK


if w.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION,
              SCRIPT_LICENSE, SCRIPT_DESC, '', ''):
    if IMPORT_ERR:
        w.prnt("", "You need sqlite3 to run this plugin.")
    options = {
        'directory': 'data',
    }
    DBFILE = w.string_eval_path_home("%h/olde.sqlite3", {}, {}, options)
    if not os.path.isfile(DBFILE):
        create_db()  # init on load if file doesn't exist.

    # load the config
    url_olde_load_config()
    # config changes are reloaded
    w.hook_config('plugins.var.python.' + SCRIPT_NAME + '.*', 'url_olde_config_cb', '')
    # catch urls in buffer and send to the cb
    w.hook_print('', 'irc_privmsg', '://', 1, 'search_urls_cb', '')