summaryrefslogtreecommitdiff
path: root/irclog
diff options
context:
space:
mode:
Diffstat (limited to 'irclog')
-rw-r--r--irclog/#main/2025/10-31.txt3
-rw-r--r--irclog/index.html0
-rw-r--r--irclog/linksub.js130
-rw-r--r--irclog/nginx.config9
-rw-r--r--irclog/view.html114
5 files changed, 256 insertions, 0 deletions
diff --git a/irclog/#main/2025/10-31.txt b/irclog/#main/2025/10-31.txt
new file mode 100644
index 0000000..46e1367
--- /dev/null
+++ b/irclog/#main/2025/10-31.txt
@@ -0,0 +1,3 @@
+[00:00:00] <alice>: hello.
+[00:00:01] <bob>: bye.
+
diff --git a/irclog/index.html b/irclog/index.html
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/irclog/index.html
diff --git a/irclog/linksub.js b/irclog/linksub.js
new file mode 100644
index 0000000..f855435
--- /dev/null
+++ b/irclog/linksub.js
@@ -0,0 +1,130 @@
+(function() {
+ 'use strict';
+
+ const targetUrlPattern = /https:\/\/raye\.mistivia\.com\/irclog\/([^/]+)\/(\d+)\/$/;
+
+ const currentUrl = window.location.href;
+
+ const match = currentUrl.match(targetUrlPattern);
+
+ if (match) {
+ let channel = match[1];
+ let year = match[2];
+
+ channel = channel.replace(/%23/g, '#');
+ year = year.replace(/%23/g, '#');
+
+ const links = document.querySelectorAll('a');
+
+ links.forEach(link => {
+ const originalHref = link.getAttribute('href');
+
+ if (originalHref && originalHref.match(/^(\d{2}-\d{2}|\d{4}-\d{2}-\d{2}|[a-zA-Z0-9_-]+)\.txt$/)) {
+
+ let datePart = originalHref.replace(/\.txt$/, '');
+
+ datePart = datePart.replace(/%23/g, '#');
+ const newHref = `https://raye.mistivia.com/irclog/view.html#${channel}/${year}/${datePart}`;
+
+ link.setAttribute('href', newHref);
+ }
+ });
+ }
+})();
+
+(function() {
+ // Check if the title starts with "Index of"
+ if (document.title.startsWith("Index of")) {
+ // --- Mobile-Friendly Styles (CSS equivalent) ---
+ var style = document.createElement('style');
+ style.textContent = `
+ body {
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
+ margin: 0;
+ padding: 15px;
+ background-color: #ffffff;
+ color: #333;
+ max-width: 900px;
+ }
+ h1 {
+ font-size: 1.8em; /* 标题稍大 */
+ margin-bottom: 15px;
+ color: #2c3e50;
+ }
+ hr {
+ border: 0;
+ border-top: 1px solid #ddd;
+ margin: 10px 0 15px 0;
+ }
+ pre {
+ white-space: pre-wrap;
+ word-wrap: break-word;
+ padding: 0;
+ margin: 0;
+ }
+
+ /* 列表项链接样式 */
+ a {
+ display: block;
+ padding: 12px 10px; /* 增加点击区域和间距 */
+ font-size: 1.2em; /* 字体大一点 */
+ text-decoration: none;
+ color: #007aff;
+ border-bottom: 1px solid #eee;
+ transition: background-color 0.2s ease; /* 添加过渡效果 */
+ }
+
+ /* 鼠标悬停变色 (桌面端) */
+ a:hover {
+ background-color: #f0f8ff; /* 浅蓝色背景 */
+ color: #005bb5; /* 链接颜色略深 */
+ }
+
+ /* 最后一个元素不显示底部分割线 */
+ pre a:last-child {
+ border-bottom: none;
+ }
+
+ /* 确保只显示文件名 */
+ .filename-only {
+ display: block !important;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ width: 100%;
+ }
+ `;
+ document.head.appendChild(style);
+ const standardContent = 'width=device-width, initial-scale=1.0, viewport-fit=cover';
+ const newViewport = document.createElement('meta');
+ newViewport.setAttribute('name', 'viewport');
+ newViewport.setAttribute('content', standardContent);
+ document.head.appendChild(newViewport);
+
+
+ // --- Clean up the Listing (JavaScript DOM Manipulation) ---
+ var pre = document.querySelector('pre');
+ if (pre) {
+
+ var links = pre.querySelectorAll('a');
+
+ // 2. Clear the original <pre> content
+ pre.textContent = '';
+
+ links.forEach(function(link) {
+ // Get the href and the filename text
+ var filename = link.textContent.trim(); // Trim whitespace
+ var href = link.getAttribute('href');
+
+ // Create a new, clean anchor element
+ var newLink = document.createElement('a');
+ newLink.setAttribute('href', href);
+ newLink.classList.add('filename-only');
+ newLink.textContent = filename; // Only the filename
+
+ // Append the clean link to the <pre> block
+ pre.appendChild(newLink);
+ });
+ }
+ }
+})();
diff --git a/irclog/nginx.config b/irclog/nginx.config
new file mode 100644
index 0000000..d00dae1
--- /dev/null
+++ b/irclog/nginx.config
@@ -0,0 +1,9 @@
+server {
+ # ...
+ location /irclog/ {
+ charset UTF-8;
+ autoindex on;
+ sub_filter_types text/html;
+ sub_filter '</body>' '<script src="/irclog/linksub.js"></script></body>';
+ }
+}
diff --git a/irclog/view.html b/irclog/view.html
new file mode 100644
index 0000000..6d8385c
--- /dev/null
+++ b/irclog/view.html
@@ -0,0 +1,114 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>IRC Log Viewer</title>
+ <style>
+ body {
+ font-family: Arial, sans-serif;
+ max-width: 1000px;
+ margin: 20px;
+ background-color: #f4f4f4;
+ }
+ #log-container {
+ border: 1px solid #ccc;
+ padding: 15px;
+ background-color: #fff;
+ white-space: pre-wrap;
+ }
+ pre {
+ font-family: Consolas, monospace;
+ margin: 0;
+ padding: 0;
+ overflow-wrap: anywhere;
+ white-space: pre-wrap;
+ }
+ .error {
+ color: red;
+ font-weight: bold;
+ }
+ .loading {
+ color: blue;
+ }
+ </style>
+</head>
+<body>
+
+ <h1>IRC Log Viewer</h1>
+ <div id="status"></div>
+ <div id="log-container">
+ </div>
+
+ <script>
+ document.addEventListener('DOMContentLoaded', () => {
+ const statusDiv = document.getElementById('status');
+ const logContainer = document.getElementById('log-container');
+
+ let urlHash = window.location.hash.substring(1);
+
+ if (!urlHash) {
+ statusDiv.className = 'error';
+ statusDiv.textContent = 'Error: No hash fragment found in the URL. Please append a hash (e.g., #2023-01-01) to the URL.';
+ return;
+ }
+ urlHash = urlHash.replace(/#/g, '%23');
+ const logBaseUrl = 'https://raye.mistivia.com/irclog/';
+ let targetUrl = `${logBaseUrl}${urlHash}.txt`; // 假设日志文件是 .txt 格式
+
+ statusDiv.className = 'loading';
+ statusDiv.textContent = `Loading log for: ${urlHash} from ${targetUrl} ...`;
+ logContainer.innerHTML = '';
+
+ // --- 新增: HTML特殊字符转义函数 ---
+ function escapeHtml(unsafe) {
+ if (!unsafe) return '';
+ // 替换 <, >, &, "
+ return unsafe
+ .replace(/&/g, "&amp;")
+ .replace(/</g, "&lt;")
+ .replace(/>/g, "&gt;")
+ .replace(/"/g, "&quot;")
+ .replace(/'/g, "&#039;");
+ }
+
+ function ircAction(text) {
+ const regex =
+ /^(\[[^\]]+\])(\s*<)([^>]+)(>:\s*)(\u0001ACTION\s+)([^\u0001]+)(\u0001)(.*)$/gm;
+ const replacement = '$1 * $3 $6$8';
+ return text.replace(regex, replacement);
+ }
+
+ function linkify(text) {
+ const urlRegex = /(\b(https?):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
+ return text.replace(urlRegex, function(url) {
+ return `<a href="${url}" target="_blank">${url}</a>`;
+ });
+ }
+
+ fetch(targetUrl)
+ .then(response => {
+ if (!response.ok) {
+ throw new Error(`HTTP Error: ${response.status} ${response.statusText} for hash: ${urlHash}`);
+ }
+ return response.text();
+ })
+ .then(text => {
+ statusDiv.textContent = ''
+ statusDiv.className = '';
+ text = ircAction(text);
+ let safeText = escapeHtml(text);
+
+ const finalHtml = linkify(safeText);
+ logContainer.innerHTML = `<pre>${finalHtml}</pre>`;
+ })
+ .catch(error => {
+ console.error('Fetch error:', error);
+ statusDiv.className = 'error';
+ statusDiv.textContent = `Failed to load log. ${error.message}`;
+ logContainer.innerHTML = `<pre class="error">Could not fetch log. Please check the console for details. (CORS or network issue likely).</pre>`;
+ });
+ });
+ </script>
+
+</body>
+</html>