feat: bot

This commit is contained in:
hashbro
2026-08-15 23:05:51 +08:00
parent 9049fdccad
commit 376b442880
26 changed files with 944 additions and 352 deletions
+50 -5
View File
@@ -33,6 +33,9 @@
<script type="text/html" id="LAY-agent-ops">
<a class="layui-btn layui-btn-primary layui-btn-xs" lay-event="channels">渠道链接</a>
<a class="layui-btn layui-btn-warm layui-btn-xs" lay-event="edit">编辑</a>
@{{# if (d.telegram_ready) { }}
<a class="layui-btn layui-btn-xs" lay-event="tgtest">测试TG</a>
@{{# } }}
</script>
</div>
</div>
@@ -43,6 +46,8 @@
layui.use(['table', 'form', 'layer'], function () {
var table = layui.table, form = layui.form, layer = layui.layer, $ = layui.$;
var token = @json(csrf_token());
var botUsername = @json($botUsername ?? '');
var botInviteUrl = @json($botInviteUrl ?? '');
function esc(s) {
return String(s == null ? '' : s)
@@ -72,7 +77,7 @@ layui.use(['table', 'form', 'layer'], function () {
{ field: 'comment', title: '备注', minWidth: 100 },
{ field: 'channels_count', title: '渠道数', width: 90 },
{ field: 'created_at', title: '创建时间', width: 160, sort: true },
{ title: '操作', width: 180, align: 'center', fixed: 'right', toolbar: '#LAY-agent-ops' }
{ title: '操作', width: 240, align: 'center', fixed: 'right', toolbar: '#LAY-agent-ops' }
]],
page: true, limit: 20, limits: [10, 20, 30, 50],
request: { pageName: 'page', limitName: 'limit' },
@@ -97,17 +102,45 @@ layui.use(['table', 'form', 'layer'], function () {
'<input name="password" type="password" class="layui-input" placeholder="' + (values.id ? '留空不改' : '必填') + '"></div></div>' +
'<div class="layui-form-item"><label class="layui-form-label">备注</label><div class="layui-input-block">' +
'<input name="comment" class="layui-input" value="' + esc(values.comment || '') + '"></div></div>' +
'<div class="layui-form-item"><label class="layui-form-label">Bot Token</label><div class="layui-input-block">' +
'<input name="bot_token" class="layui-input" placeholder="代理 Telegram Bot Token" value="' + esc(values.bot_token || '') + '"></div></div>' +
'<div class="layui-form-item"><label class="layui-form-label">Chat ID</label><div class="layui-input-block">' +
'<input name="chat_id" class="layui-input" placeholder="代理通知群 chat_id" value="' + esc(values.chat_id || '') + '"></div></div>' +
'<div class="layui-form-item"><div class="layui-input-block" style="color:#888;font-size:12px;line-height:1.5;">配置后该代理渠道通知发往此 Bot/群;指令仅可查本代理数据,不支持 /transfer。<br>Webhook: <code>/hooks/telegram/agent/{id}</code>,保存后执行 <code>php artisan telegram:set-webhook --agent={id}</code></div></div>' +
'<div style="display:flex;gap:8px;align-items:center;">' +
'<input name="chat_id" class="layui-input" placeholder="代理通知群 chat_id" value="' + esc(values.chat_id || '') + '" style="flex:1;">' +
'<button type="button" class="layui-btn layui-btn-primary" id="LAY-agent-tg-test" style="flex-shrink:0;">测试推送</button>' +
'</div></div></div>' +
'<div class="layui-form-item"><div class="layui-input-block" style="color:#888;font-size:12px;line-height:1.5;">' +
(botUsername
? '请邀请 <b>' + esc(botUsername) + '</b> 进群' + (botInviteUrl ? '(<a href="' + esc(botInviteUrl) + '" target="_blank" rel="noopener">点此邀请</a>)' : '') + ',进群后 Bot 会回复 Chat ID,再填到这里。'
: '请先在系统设置保存有效 Bot Token(会自动识别 @用户名),再邀请该 Bot 进群。') +
' 填 Chat ID 后,该代理渠道通知会同时发到此群和官方群。</div></div>' +
'<div class="layui-form-item"><label class="layui-form-label">状态</label><div class="layui-input-block">' +
'<input type="checkbox" name="status_switch" lay-skin="switch" lay-text="启用|禁用" ' + ((values.status == null || values.status == 1) ? 'checked' : '') + '>' +
'</div></div>' +
'</form>',
success: function () {
form.render();
$('#LAY-agent-tg-test').on('click', function () {
var $btn = $(this);
if ($btn.prop('disabled')) return;
$btn.prop('disabled', true);
$.ajax({
url: @json(route('admin.agents.telegramTest')),
method: 'POST',
data: {
_token: token,
chat_id: $('#LAY-agent-form input[name=chat_id]').val(),
agent_id: values.id || ''
},
success: function (res) {
layer.msg(res.msg || (res.code === 0 ? '已发送' : '失败'));
},
error: function (xhr) {
layer.msg((xhr.responseJSON && xhr.responseJSON.message) || '测试失败');
},
complete: function () {
$btn.prop('disabled', false);
}
});
});
},
btn: ['保存', '取消'],
yes: function (index) {
@@ -154,6 +187,18 @@ layui.use(['table', 'form', 'layer'], function () {
}
});
});
} else if (obj.event === 'tgtest') {
$.ajax({
url: @json(route('admin.agents.telegramTest')),
method: 'POST',
data: { _token: token, agent_id: d.id, chat_id: d.chat_id },
success: function (res) {
layer.msg(res.msg || (res.code === 0 ? '已发送' : '失败'));
},
error: function (xhr) {
layer.msg((xhr.responseJSON && xhr.responseJSON.message) || '测试失败');
}
});
} else if (obj.event === 'channels') {
$.getJSON(@json(url('/admin/agents')) + '/' + d.id + '/channels', function (res) {
var html = (res.data || []).map(function (c) {
@@ -15,13 +15,33 @@
<div class="layui-input-block">
<input type="text" name="telegram_bot_token" class="layui-input" autocomplete="off"
value="{{ $form['telegram.bot_token'] }}">
<div class="layui-form-mid layui-word-aux" id="LAY-telegram-bot-name">
@if($botUsername)
当前 Bot:<b>{{ $botUsername }}</b>
@if($botInviteUrl)
· <a href="{{ $botInviteUrl }}" target="_blank" rel="noopener">邀请进群</a>
@endif
@else
保存 Token 后会通过 Telegram getMe 自动识别 @用户名,无需手填。
@endif
</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">Chat ID</label>
<div class="layui-input-block">
<input type="text" name="telegram_owner_chat_id" class="layui-input" autocomplete="off"
value="{{ $form['telegram.owner_chat_id'] }}" placeholder="个人或群组 chat_id">
<div style="display:flex;gap:8px;align-items:center;max-width:640px;">
<input type="text" name="telegram_owner_chat_id" class="layui-input" autocomplete="off"
value="{{ $form['telegram.owner_chat_id'] }}" placeholder="官方通知群 chat_id" style="flex:1;">
<button type="button" class="layui-btn layui-btn-primary" id="LAY-telegram-test" style="flex-shrink:0;">测试推送</button>
</div>
<div class="layui-form-mid layui-word-aux" id="LAY-telegram-chat-hint">
@if($botUsername)
请邀请 <b>{{ $botUsername }}</b> 进群(进群后 Bot 会回复 Chat ID),再填到这里。全站共用这一个 Bot;代理单独推送只需在「代理用户」里填 Chat ID。
@else
全站共用这一个 Bot。此处为官方通知群;代理单独推送只需在「代理用户」里填 Chat ID。保存 Token 后会提示要邀请哪个 Bot。
@endif
</div>
</div>
</div>
@@ -88,6 +108,17 @@ layui.use(['form', 'layer'], function () {
data: Object.assign({}, data.field, { _token: token }),
success: function (res) {
layer.msg(res.msg || (res.code === 0 ? '已保存' : '失败'));
if (res.code === 0 && res.data) {
var name = res.data.bot_username || '';
var url = res.data.bot_invite_url || '';
if (name) {
var invite = url ? ' · <a href="' + url + '" target="_blank" rel="noopener">邀请进群</a>' : '';
$('#LAY-telegram-bot-name').html('当前 Bot:<b>' + name + '</b>' + invite);
$('#LAY-telegram-chat-hint').html('请邀请 <b>' + name + '</b> 进群(进群后 Bot 会回复 Chat ID),再填到这里。全站共用这一个 Bot;代理单独推送只需在「代理用户」里填 Chat ID。');
} else {
$('#LAY-telegram-bot-name').text('保存 Token 后会通过 Telegram getMe 自动识别 @用户名,无需手填。');
}
}
},
error: function (xhr) {
layer.msg((xhr.responseJSON && xhr.responseJSON.message) || '保存失败');
@@ -95,6 +126,30 @@ layui.use(['form', 'layer'], function () {
});
return false;
});
$('#LAY-telegram-test').on('click', function () {
var $btn = $(this);
if ($btn.prop('disabled')) return;
$btn.prop('disabled', true);
$.ajax({
url: @json(route('admin.system.settings.telegramTest')),
method: 'POST',
data: {
_token: token,
chat_id: $('input[name=telegram_owner_chat_id]').val(),
bot_token: $('input[name=telegram_bot_token]').val()
},
success: function (res) {
layer.msg(res.msg || (res.code === 0 ? '已发送' : '失败'));
},
error: function (xhr) {
layer.msg((xhr.responseJSON && xhr.responseJSON.message) || '测试失败');
},
complete: function () {
$btn.prop('disabled', false);
}
});
});
});
</script>
@endpush