fb-bot_discord

xctf的一血机器人播报,内含源码。

基础知识

初始化bot

首先需要创建一个机器人,在这个网站注册一个账号,之后在应用这里注册一个机器人

image-20220401215407780

我这里命名为bot_test。点开之后,点击左边的bot,点击add_bot

image-20220401215626646

点击生成一个token。如下图。这个token是在本地控制机器人的唯一方式。因此千万不能泄露。

image-20220401215752532

之后点击左边的OAUTH2。选择下面的选项。这里的选项是bot的权限。按照自己的需要添加就行。

image-20220401220007265

比如作为一个fb-bot可能只要选择这些就可以了。接着我们点这里的copy。吧URL复制到浏览器里面并点击。

image-20220401220227350

可以看到它让我们选择一个服务器。这个服务器就是我们作为管理员所在的服务器。

image-20220401220333083

本地构建bot环境

这里需要介绍一些discord的API。以及一些需要安装的库。最好把下面这些都装了

1
2
3
4
5
6
7
8
9
from aiohttp.client import request
import discord
from aiohttp_socks import ProxyConnector
from discord.ext import tasks, commands
from discord.ext.commands import Bot
from discord import utils
import requests
from requests import sessions
import json

其次,需要一个VPN。我这里用的是clash。直接用他的默认端口7890就可以了。注意,clash默认打开的时候不会开启socks5端口。我们需要按照以下步骤操作:

  1. 打开clash

image-20220401220827552

  1. 进入windows Internet属性这里,修改如下所示的套接字部分。这里要保持安全这里写空,不然不知道为什么xctf的SSL验证无法通过(真是糟心…)

image-20220401231447090

之后就可以了。注意不能把上面两步倒过来,因为clash打开的时候会默认重置上面我们添加的内容。

实现代码

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
from aiohttp.client import request
import discord
from aiohttp_socks import ProxyConnector
from discord.ext import tasks, commands
from discord.ext.commands import Bot
from discord import utils
import requests
from requests import sessions
import json

# 注意bot必须通过这个协议,不知道为什么。按照上面的做就行了。
bot = Bot("!", connector =ProxyConnector.from_url('socks5://127.0.0.1:7890'))
TOKEN = "上面基础知识拿到的token"
# 下面这五个怎么拿到会在代码后面写
MY_GUILD=959118584083279952
MY_CHANNEL=959118584083279954
XCTF_GUILD=941157903128223805
XCTF_TEST_CHANNEL=941200329968603187
XCTF_REAL_CHANNEL=941198787580412005 # announcement
@bot.event
async def on_ready():
print('We have logged in as {0.user}'.format(bot))
await bot.get_channel(XCTF_TEST_CHANNEL).send("Bot is online")


class MyCog(commands.Cog):
def __init__(self, bot, index):
self.index = index
self.bot = bot
self.first_blood.start()

def cog_unload(self):
self.first_blood.cancel()
# 下面的seconds是每隔多久时间访问xctf来更新一血列表
@tasks.loop(seconds=60)
async def first_blood(self):
await self.bot.wait_until_ready()
# print("check1")
# 这里的ID是读取json返回数据中比当前参数输入id更大的所有消息,以及notice。但是要确保收到一血消息,检查is_task字段即可。
print(self.index)
guild = self.bot.get_guild(XCTF_GUILD)
# 注意下面的evt要根据不同的比赛修改
res = requests.get('https://adworld.xctf.org.cn/api/evts/notices', params={'evt': 171, 'id': self.index}, cookies={'session': '访问上述网页看到的session'})
res.encoding = 'Unicode'
result_text = res.text
# 将text转换为json并分析
json_data = json.loads(result_text)
# print(json_data)
for item in json_data:
# 这个json_data怎么选的下面会写
if (item['is_task'] == 1):
# name = 'first-blood'
name = 'main-chat'
if(item['id'] > self.index):
self.index = item['id']
# name这里写要发送到的channel的名字。
await utils.get(guild.text_channels,name=name).send(item['notice'])
# else:
# name = 'announcement'
# await utils.get(guild.text_channels,name=name).send(item['notice'])
print(item)

@commands.command()
async def stop(self, ctx):
if ctx.channel.name == 'main-chat': # 能够控制bot的命令只有发在main-chat里面才反应
await ctx.send('Bye!')
await bot.close()


bot.add_cog(MyCog(bot, int(input('index: '))))

bot.run(TOKEN)
  1. 如何找到server guild可以参考下文。
    https://poshbot.readthedocs.io/en/latest/guides/backends/setup-discord-backend/#find-your-guild-id-server-id

image-20220401131038584

  1. 如何找到channel?连接的最后一个反斜杠后面的就是

image-20220401221639322

  1. 为什么json这样写,可以打开一个上面代码第44行的网站看一眼就知道了。

image-20220401221149760

可以看到xctf发出的信息都是这种格式。注意is_task字段,这个区分了是announcement还是一血播报。我们只要根据这个,然后提取出notice就可以了。另外注意每次请求的URL里面的id是返回内容中最小的id。举个例子上面可以看到消息id最大是2271.那么如果请求id=2200就会显示2200到2271的所有消息。所以每一次请求完,要记录一下最新的ID,防止重复播报一血。这一点在代码56行体现。

  1. session怎么看?

我安装了火狐插件EditThisCookie。可以直接在这里看到。

image-20220401221850416

发个命令测试,都是没问题的

image-20220401221958874

上述bot只是实现了最简单的一血播报。想不到还有什么好玩的命令了。

文章目录
  1. 1. 基础知识
    1. 1.1. 初始化bot
    2. 1.2. 本地构建bot环境
  2. 2. 实现代码
|