This commit is contained in:
浪子 2024-12-13 08:08:08 +08:00
parent 4bc9e98199
commit 0cfafd5433
6 changed files with 2390 additions and 27 deletions

1994
Parsedown.php Normal file

File diff suppressed because it is too large Load Diff

View File

@ -103,12 +103,15 @@ function threadedComments($comments, $options) {
</div>
<div class="comment--meta">
<div class="comment--author"><?php echo $comments->author; ?>
<?php if ($comments->authorId == $comments->ownerId): ?>
<span class="dot"></span> <span class="custom-span">作者</span>
<?php endif; ?>
<span class="dot"></span>
<?php $commentApprove = commentApprove($comments, $comments->mail); ?>
<span style="color: <?php echo $commentApprove['bgColor']; ?>;">
<?php echo $commentApprove['userLevel']; ?>
</span>
<span class="dot"></span>
<div class="comment--time"><?php $comments->date('Y-m-d H:i'); ?></div>
<span class="dot"></span>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="12" height="12" fill="currentColor"><path d="M12 20.8995L16.9497 15.9497C19.6834 13.2161 19.6834 8.78392 16.9497 6.05025C14.2161 3.31658 9.78392 3.31658 7.05025 6.05025C4.31658 8.78392 4.31658 13.2161 7.05025 15.9497L12 20.8995ZM12 23.7279L5.63604 17.364C2.12132 13.8492 2.12132 8.15076 5.63604 4.63604C9.15076 1.12132 14.8492 1.12132 18.364 4.63604C21.8787 8.15076 21.8787 13.8492 18.364 17.364L12 23.7279ZM12 13C13.1046 13 14 12.1046 14 11C14 9.89543 13.1046 9 12 9C10.8954 9 10 9.89543 10 11C10 12.1046 10.8954 13 12 13ZM12 15C9.79086 15 8 13.2091 8 11C8 8.79086 9.79086 7 12 7C14.2091 7 16 8.79086 16 11C16 13.2091 14.2091 15 12 15Z"></path></svg><?php echo convertip($comments->ip); ?>
<span class="comment-reply-link u-cursorPointer">
<?php $comments->reply('<svg viewBox="0 0 24 24" width="14" height="14" aria-hidden="true" class="" ><g><path d="M12 3.786c-4.556 0-8.25 3.694-8.25 8.25s3.694 8.25 8.25 8.25c1.595 0 3.081-.451 4.341-1.233l1.054 1.7c-1.568.972-3.418 1.534-5.395 1.534-5.661 0-10.25-4.589-10.25-10.25S6.339 1.786 12 1.786s10.25 4.589 10.25 10.25c0 .901-.21 1.77-.452 2.477-.592 1.731-2.343 2.477-3.917 2.334-1.242-.113-2.307-.74-3.013-1.647-.961 1.253-2.45 2.011-4.092 1.78-2.581-.363-4.127-2.971-3.76-5.578.366-2.606 2.571-4.688 5.152-4.325 1.019.143 1.877.637 2.519 1.342l1.803.258-.507 3.549c-.187 1.31.761 2.509 2.079 2.629.915.083 1.627-.356 1.843-.99.2-.585.345-1.224.345-1.83 0-4.556-3.694-8.25-8.25-8.25zm-.111 5.274c-1.247-.175-2.645.854-2.893 2.623-.249 1.769.811 3.143 2.058 3.319 1.247.175 2.645-.854 2.893-2.623.249-1.769-.811-3.144-2.058-3.319z"></path></g></svg>'); ?>
</span>
@ -127,26 +130,3 @@ function threadedComments($comments, $options) {
<?php } ?>
</li>
<?php } ?>
<style>.custom-span {
display: inline-flex;
align-items: center;
font-weight: 500; /* Equivalent to font-medium */
border-radius: 0.375rem; /* Equivalent to rounded-md */
font-size: 0.75rem; /* Equivalent to text-xs */
padding-left: 1.5px; /* Equivalent to px-1.5 */
padding-right: 1.5px; /* Equivalent to px-1.5 */
padding-top: 0.5px; /* Equivalent to py-0.5 */
padding-bottom: 0.5px; /* Equivalent to py-0.5 */
border: 1px solid var(--farallon-border-color); /* ring-1 and ring-inset with ring-gray-300 */
color: var(--farallon-text-gray); /* text-gray-700 */
background: var(--farallon-background-gray); /* bg-gray-50 */
}
/* Dark mode styles */
@media (prefers-color-scheme: dark) {
.custom-span {
border-color: var(--farallon-hover-color); /* ring-gray-700 */
color: var(--farallon-hover-color); /* text-gray-200 */
background-color: var(--farallon-background-gray); /* bg-gray-800 */
}
}</style>

BIN
dist/qqwry.dat vendored Normal file

Binary file not shown.

View File

@ -1,5 +1,6 @@
<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
require 'ipdata.class.php';
function themeConfig($form) {
$logoUrl = new Typecho_Widget_Helper_Form_Element_Text('logoUrl', NULL, NULL, _t('站点 LOGO 地址'));
$form->addInput($logoUrl);
@ -385,3 +386,96 @@ EOF;
// 注册编辑器按钮钩子
Typecho_Plugin::factory('admin/write-post.php')->bottom = array('EditorButton', 'render');
Typecho_Plugin::factory('admin/write-page.php')->bottom = array('EditorButton', 'render');
/**
* 评论者认证等级 + 身份
*
* @author Chrison
* @access public
* @param str $email 评论者邮址
* @return result
*/
function commentApprove($widget, $email = NULL)
{
$result = array(
"state" => -1,//状态
"isAuthor" => 0,//是否是博主
"userLevel" => '',//用户身份或等级名称
"userDesc" => '',//用户title描述
"bgColor" => '',//用户身份或等级背景色
"commentNum" => 0//评论数量
);
if (empty($email)) return $result;
$result['state'] = 1;
$master = array(
'基友邮箱1@qq.com',
'基友邮箱1@qq.com'
);
if ($widget->authorId == $widget->ownerId) {
$result['isAuthor'] = 1;
$result['userLevel'] = '博主';
$result['userDesc'] = '很帅的博主';
$result['bgColor'] = '#FFD700';
$result['commentNum'] = 999;
} else if (in_array($email, $master)) {
$result['userLevel'] = '基友';
$result['userDesc'] = '很帅的基友';
$result['bgColor'] = '#65C186';
$result['commentNum'] = 888;
} else {
//数据库获取
$db = Typecho_Db::get();
//获取评论条数
$commentNumSql = $db->fetchAll($db->select(array('COUNT(cid)'=>'commentNum'))
->from('table.comments')
->where('mail = ?', $email));
$commentNum = $commentNumSql[0]['commentNum'];
//获取友情链接
$linkSql = $db->fetchAll($db->select()->from('table.links')
->where('user = ?',$email));
//等级判定
if($commentNum==1){
$result['userLevel'] = '初识';
$result['bgColor'] = '#999999';
$userDesc = '你已经向目的地迈出了第一步!';
} else {
if ($commentNum<3 && $commentNum>1) {
$result['userLevel'] = '初识';
$result['bgColor'] = '#999999';
}elseif ($commentNum<9 && $commentNum>=3) {
$result['userLevel'] = '朋友';
$result['bgColor'] = '#A0DAD0';
}elseif ($commentNum<27 && $commentNum>=9) {
$result['userLevel'] = '好友';
$result['bgColor'] = '#FF8C00';
}elseif ($commentNum<81 && $commentNum>=27) {
$result['userLevel'] = '挚友';
$result['bgColor'] = '#FF0000';
}elseif ($commentNum<100 && $commentNum>=81) {
$result['userLevel'] = '兄弟';
$result['bgColor'] = '#006400';
}elseif ($commentNum>=100) {
$result['userLevel'] = '老铁';
$result['bgColor'] = '#A0DAD0';
}
$userDesc = '你已经向目的地前进了'.$commentNum.'步!';
}
if($linkSql){
$result['userLevel'] = '博友';
$result['bgColor'] = '#21b9bb';
$userDesc = '🔗'.$linkSql[0]['description'].'&#10;✌️'.$userDesc;
}
$result['userDesc'] = $userDesc;
$result['commentNum'] = $commentNum;
}
return $result;
}
/** 获取评论者归属地信息 */
function convertip($ip){
echo convertips($ip);
}

132
ipdata.class.php Normal file
View File

@ -0,0 +1,132 @@
<?php
/** 获取评论者地址 */
function convertips($ip){
$ip1num = 0;
$ip2num = 0;
$ipAddr1 ="";
$ipAddr2 ="";
$dat_path = dirname(__FILE__).'/dist/qqwry.dat';
if(!preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/", $ip)) {
return 'IPV6无法获取归宿地';
}
if(!$fd = @fopen($dat_path, 'rb')){
return 'IP 数据库路径不正确';
}
$ip = explode('.', $ip);
$ipNum = $ip[0] * 16777216 + $ip[1] * 65536 + $ip[2] * 256 + $ip[3];
$DataBegin = fread($fd, 4);
$DataEnd = fread($fd, 4);
$ipbegin = implode('', unpack('L', $DataBegin));
if($ipbegin < 0) $ipbegin += pow(2, 32);
$ipend = implode('', unpack('L', $DataEnd));
if($ipend < 0) $ipend += pow(2, 32);
$ipAllNum = ($ipend - $ipbegin) / 7 + 1;
$BeginNum = 0;
$EndNum = $ipAllNum;
while($ip1num>$ipNum || $ip2num<$ipNum) {
$Middle= intval(($EndNum + $BeginNum) / 2);
fseek($fd, $ipbegin + 7 * $Middle);
$ipData1 = fread($fd, 4);
if(strlen($ipData1) < 4) {
fclose($fd);
return 'System Error';
}
$ip1num = implode('', unpack('L', $ipData1));
if($ip1num < 0) $ip1num += pow(2, 32);
if($ip1num > $ipNum) {
$EndNum = $Middle;
continue;
}
$DataSeek = fread($fd, 3);
if(strlen($DataSeek) < 3) {
fclose($fd);
return 'System Error';
}
$DataSeek = implode('', unpack('L', $DataSeek.chr(0)));
fseek($fd, $DataSeek);
$ipData2 = fread($fd, 4);
if(strlen($ipData2) < 4) {
fclose($fd);
return 'System Error';
}
$ip2num = implode('', unpack('L', $ipData2));
if($ip2num < 0) $ip2num += pow(2, 32);
if($ip2num < $ipNum) {
if($Middle == $BeginNum) {
fclose($fd);
return 'Unknown';
}
$BeginNum = $Middle;
}
}
$ipFlag = fread($fd, 1);
if($ipFlag == chr(1)) {
$ipSeek = fread($fd, 3);
if(strlen($ipSeek) < 3) {
fclose($fd);
return 'System Error';
}
$ipSeek = implode('', unpack('L', $ipSeek.chr(0)));
fseek($fd, $ipSeek);
$ipFlag = fread($fd, 1);
}
if($ipFlag == chr(2)) {
$AddrSeek = fread($fd, 3);
if(strlen($AddrSeek) < 3) {
fclose($fd);
return 'System Error';
}
$ipFlag = fread($fd, 1);
if($ipFlag == chr(2)) {
$AddrSeek2 = fread($fd, 3);
if(strlen($AddrSeek2) < 3) {
fclose($fd);
return 'System Error';
}
$AddrSeek2 = implode('', unpack('L', $AddrSeek2.chr(0)));
fseek($fd, $AddrSeek2);
} else {
fseek($fd, -1, SEEK_CUR);
}
while(($char = fread($fd, 1)) != chr(0))
$ipAddr2 .= $char;
$AddrSeek = implode('', unpack('L', $AddrSeek.chr(0)));
fseek($fd, $AddrSeek);
while(($char = fread($fd, 1)) != chr(0))
$ipAddr1 .= $char;
} else {
fseek($fd, -1, SEEK_CUR);
while(($char = fread($fd, 1)) != chr(0))
$ipAddr1 .= $char;
$ipFlag = fread($fd, 1);
if($ipFlag == chr(2)) {
$AddrSeek2 = fread($fd, 3);
if(strlen($AddrSeek2) < 3) {
fclose($fd);
return 'System Error';
}
$AddrSeek2 = implode('', unpack('L', $AddrSeek2.chr(0)));
fseek($fd, $AddrSeek2);
} else {
fseek($fd, -1, SEEK_CUR);
}
while(($char = fread($fd, 1)) != chr(0)){
$ipAddr2 .= $char;
}
}
fclose($fd);
if(preg_match('/http/i', $ipAddr2)) {
$ipAddr2 = '';
}
$ipaddr = "$ipAddr1 $ipAddr2";
$ipaddr = preg_replace('/CZ88.NET/is', '', $ipaddr);
$ipaddr = preg_replace('/^s*/is', '', $ipaddr);
$ipaddr = preg_replace('/s*$/is', '', $ipaddr);
if(preg_match('/http/i', $ipaddr) || $ipaddr == '') {
$ipaddr = '可能来自火星';
}
$ipaddr = iconv('gbk', 'utf-8//IGNORE', $ipaddr);
return $ipaddr;
}
?>

163
tooot.php Normal file
View File

@ -0,0 +1,163 @@
<?php
/**
* 说说页面1 - Mastodon
*
* @package custom
*/
if (!defined('__TYPECHO_ROOT_DIR__')) exit; ?>
<?php $this->need('header.php'); ?>
<div class="site--main">
<header class="archive--header">
<h1 class="post--single__title"><?php $this->title() ?></h1>
<h2 class="post--single__subtitle"><?php $this->content(); ?> </h2>
</header>
<article class="post--single">
<?php
require 'Parsedown.php';
use Parsedown;
// 获取 API 地址
$tooot = $this->fields->tooot ? $this->fields->tooot : 'https://bbapi.ima.cm';
// 获取当前页码,默认为第一页
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
// 每页显示的数量
$limit = 20;
// 计算偏移量
$offset = ($page - 1) * $limit;
// 使用 file_get_contents 获取数据
$data = file_get_contents($tooot);
$toots = json_decode($data, true);
// 只获取当前页的数据
$tootsToShow = array_slice($toots, $offset, $limit);
// 初始化 Parsedown
$parsedown = new Parsedown();
?>
<script src="<?php $this->options->themeUrl('/dist/js/marked.min.js'); ?>"></script>
<script src="<?php $this->options->themeUrl('/dist/js/view-image.min.js'); ?>"></script>
<div id="tooot">
<?php foreach ($tootsToShow as $toot): ?>
<article class='post--item post--item__status'>
<div class='content'>
<header>
<img src="<?php echo $toot['account']['avatar']; ?>" class="avatar" width="48" height="48" no-view />
<a class="humane--time" href="<?php echo $toot['url']; ?>" target="_blank"><?php echo date('Y-m-d H:i:s', strtotime($toot['created_at'])); ?></a>
</header>
<div class="description" itemprop="about">
<?php echo $parsedown->text($toot['content']); ?>
<div class="resimg">
<?php foreach ($toot['media_attachments'] as $attachment): ?>
<?php if ($attachment['type'] === 'image'): ?>
<a href="<?php echo $attachment['url']; ?>" target="_blank"><img src="<?php echo $attachment['preview_url']; ?>" class="thumbnail-image img"></a>
<?php endif; ?>
<?php endforeach; ?>
</div>
</div>
</div>
</article>
<?php endforeach; ?>
</div>
<div class="nav-links" id="loadmore">
<?php if ($offset + $limit < count($toots)): ?>
<a href="?page=<?php echo $page + 1; ?>" class="loadmore">加载更多</a>
<?php endif; ?>
</div>
<script>
window.ViewImage && ViewImage.init('.content img');
</script>
</article>
<style>
div pre code {
/* 迫使文字断行 */
white-space: pre-wrap; /* CSS3 */
word-wrap: break-word; /* 老版本的浏览器 */
overflow-wrap: break-word;
word-break: break-all;
word-break: break-word;
}
div p a {
word-break: break-all;
word-break: break-word;
}
.resimg {
display: grid;
grid-template-columns: repeat(3, 1fr);
column-gap: 10px;
row-gap: 10px;
}
/* 单个缩略图的样式 */
.thumbnail-image {
width: 100%; /* 确保其宽度填满父容器 */
height: 200px; /* 固定高度 */
display: flex; /* 使用 flexbox 居中 */
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
overflow: hidden; /* 确保容器内的多余内容不会显示出来 */
border-radius: 4px; /* 圆角 */
transition: transform .3s ease; /* 鼠标悬停时的过渡效果 */
cursor: zoom-in; /* 鼠标指针变为放大镜 */
}
img {
object-fit: cover; /* 保持图片的纵横比,但会将图片裁剪以填充容器 */
object-position: center; /* 保证中央部分 */
}
/* 缩略图内的图片样式 */
.thumbnail-image img {
width: 100%;
min-height: 200px;
}
/* 当屏幕宽度小于732px时 */
@media (max-width: 732px) {
.resimg {
grid-template-columns: repeat(2, 1fr); /* 修改为两列 */
}
}
/* 当屏幕宽度小于400px时 */
@media (max-width: 400px) {
.resimg {
grid-template-columns: 1fr; /* 修改为一列 */
}
.thumbnail-image img {
width: 100%;
height: 480px;
}
}
.load-more-btn {
display: block;
margin: 20px auto;
padding: 10px 20px;
background-color: #007bff;
color: white;
border: none;
cursor: pointer;
border-radius: 5px;
}
.load-more-btn:hover {
background-color: #0056b3;
}
.nav-links .loadmore {
border: 1px solid var(--farallon-border-color);
cursor: pointer;
position: relative;
padding: 5px 30px;
border-radius: 8px;
font-size: 14px;
color: var(--farallon-text-gray)
}
.nav-links .loadmore:hover {
border-color: var(--farallon-hover-color);
color: var(--farallon-hover-color)
}
</style>
</div>
<?php $this->need('footer.php'); ?>