This site is developed to XHTML and CSS2 W3C standards. If you see this paragraph, your browser does not support those standards and you need to upgrade. Visit WaSP for a variety of options.

php pastebin - collaborative irc debugging view php source

Paste #661

Posted by: url.py
Posted on: 2026-03-15 20:58:46
Age: 3 hrs ago
Views: 8
# -*- coding: utf-8 -*-
"""
Название:   UrlTitle.py
Описание:   Показывает заголовок страницы при отправке любой ссылки в чат
Версия:     0.4
Автор:      адаптация под 2025–2026
"""

__module_name__        = "UrlTitle"
__module_version__     = "0.4"
__module_description__ = "Показывает <title> страницы при отправке ссылок"

import hexchat
import re
import urllib.request
import urllib.error
import html
import socket

# Настройки — можно менять
TIMEOUT       = 6          # секунд на попытку скачать страницу
MAX_TITLE_LEN = 120        # обрезаем слишком длинные заголовки
USER_AGENT    = "HexChat-UrlTitle/0.4 (compatible; +https://example.com)"

# Самое простое регулярное выражение для url (http(s)://...)
URL_RE = re.compile(r'(https?://[^\s<>"\']+)', re.IGNORECASE)

# Черный список доменов, которые обычно не нужны / долго отвечают / не html
BLACKLIST = {
    "youtu.be", "youtube.com", "youtu.be", "twitter.com", "x.com",
    "t.me", "discord.com", "discordapp.com", "github.com", ".png", ".jpg",
    ".jpeg", ".gif", ".webp", ".pdf", ".zip", ".exe"
}

def is_probably_html(url):
    low = url.lower()
    for bad in BLACKLIST:
        if bad in low:
            return False
    return True

def get_title(url):
    try:
        req = urllib.request.Request(
            url,
            headers={'User-Agent': USER_AGENT}
        )
        with urllib.request.urlopen(req, timeout=TIMEOUT) as response:
            if response.getcode() != 200:
                return None

            content_type = response.headers.get('Content-Type', '').lower()
            if 'text/html' not in content_type:
                return None

            data = response.read(8192 * 2).decode('utf-8', errors='replace')
            m = re.search(r'<title[^>]*>(.*?)</title>', data, re.IGNORECASE | re.DOTALL)
            if m:
                title = html.unescape(m.group(1).strip())
                title = ' '.join(title.split())  # убираем лишние пробелы
                if len(title) > MAX_TITLE_LEN:
                    title = title[:MAX_TITLE_LEN-3] + "..."
                return title
            return None
    except (urllib.error.HTTPError, urllib.error.URLError, socket.timeout,
            UnicodeDecodeError, ConnectionResetError, OSError):
        return None

def on_message(word, word_eol, event_name, attrs=None):
    # word[0]  — ник
    # word[1]  — текст сообщения
    text = word[1]

    urls = URL_RE.findall(text)
    if not urls:
        return hexchat.EAT_NONE

    shown = set()

    for url in urls:
        if url in shown:
            continue

        # Пропускаем очевидные не-html ссылки
        if not is_probably_html(url):
            continue

        title = get_title(url)
        if title:
            # Показываем в текущем канале
            hexchat.prnt(f"→ Title: \00302{title}\003\t({url})")
            shown.add(url)

    return hexchat.EAT_NONE

def unload_cb(userdata):
    hexchat.prnt(f"→ {__module_name__} выгружен")
    return

# ────────────────────────────────────────────────
# Регистрируем хуки на все типы сообщений
# ────────────────────────────────────────────────

for event in (
    "Channel Message",
    "Your Message",           # твои сообщения
    "Channel Msg Hilight",
    "Private Message",
    "Private Message to",
):
    hexchat.hook_print(event, on_message, event, priority=hexchat.PRI_LOW)

hexchat.hook_unload(unload_cb)

hexchat.prnt(f"→ Плагин {__module_name__} {__module_version__} загружен")

Download raw | Create new paste

© BitByByte, 2026.
Downgrade Counter