new version

This commit is contained in:
xtaodada 2021-06-20 16:56:30 +08:00
parent 78f20c465b
commit 70da6de1b7
No known key found for this signature in database
GPG Key ID: EE4DC37B55E24736
10 changed files with 207 additions and 95 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.idea/
venv/

View File

@ -1,10 +1,22 @@
TOKEN = "1749418611:AAGOV2XB5mkMXqX-J_wtNu7KkrkhO_Xylmg"
TOKEN = "token here"
# 频率限制次数,每个群每小时内,只能主动触发10次任务
LIMIT_COUNT = 10
# 频率限制次数,每个群每小时内,只能主动触发2次任务
LIMIT_COUNT = 2
# 私有模式,仅授权群组可用 0:关闭 1:打开
EXCLUSIVE_MODE = 0
# 私有模式,仅授权群组可用 False:关闭 True:打开
EXCLUSIVE_MODE = False
# 主动触发命令仅管理员有效 0:否 1:是
RANK_COMMAND_MODE = 1
# 配置私有模式群组id列表不私有请忽略 例如:[-1001324252532, -100112415423]
EXCLUSIVE_LIST = []
# 主动触发命令仅管理员有效 False:否 True:是
RANK_COMMAND_MODE = True
# 中文字体路径
FRONT = 'fonts/ZhuZiAWan-2.ttc'
# Redis 配置
REDIS_CONFIG = {'host': '127.0.0.1', 'port': 6379, 'db': 1}
# 拥有者 id 配置
OWNER = 0

View File

@ -1,6 +1,8 @@
import redis
from config import REDIS_CONFIG
pool = redis.ConnectionPool(host='127.0.0.1', port=6379, encoding='utf8', decode_responses=True)
pool = redis.ConnectionPool(host=REDIS_CONFIG['host'], port=REDIS_CONFIG['port'], db=REDIS_CONFIG['db'],
encoding='utf8', decode_responses=True)
def get_connection():

BIN
fonts/ZhuZiAWan-2.ttc Normal file

Binary file not shown.

36
func.py
View File

@ -3,7 +3,7 @@ import time
import connector
import telegram
from telegram.ext import CommandHandler, MessageHandler, Filters
from config import TOKEN, LIMIT_COUNT, EXCLUSIVE_MODE, RANK_COMMAND_MODE
from config import TOKEN, LIMIT_COUNT, EXCLUSIVE_MODE, RANK_COMMAND_MODE, OWNER, EXCLUSIVE_LIST
import schedule
from task import add_task
@ -11,17 +11,21 @@ bot = telegram.Bot(token=TOKEN)
def start(update, context):
# 限制不为群组
chat_type = update.effective_chat.type
if chat_type == "supergroup":
return
try:
connector.get_connection().keys()
print('进入start函数')
update.message.reply_text(
'在呢!系统运行正常~',
'pong~',
)
except Exception as e:
print(e)
print('进入start函数')
update.message.reply_text("系统故障Redis连接失败请检查")
update.message.reply_text("错误信息:" + str(e))
if update.effective_user.id == OWNER:
update.message.reply_text(f"系统故障Redis连接失败错误信息\n{e}")
def rank(update, context):
@ -36,9 +40,9 @@ def rank(update, context):
username = update.effective_user.id
# 限制为群组
if chat_type != "supergroup":
update.message.reply_text("此命令只有在群组中有效")
update.message.reply_text("此命令只有在群组中有效")
return
if RANK_COMMAND_MODE == 1:
if RANK_COMMAND_MODE:
try:
chat_member = bot.get_chat_member(chat_id, user_id)
status = chat_member["status"]
@ -46,7 +50,6 @@ def rank(update, context):
if status == "creator" or status == "administrator":
print("用户权限正确")
else:
update.message.reply_text("此命令仅对管理员开放")
return
except Exception as e:
print(e)
@ -91,30 +94,19 @@ def chat_content_exec(update, context):
if len(text) > 80:
return
# 独享模式(仅授权群组可用)
if EXCLUSIVE_MODE == 1 and chat_id not in ["1231242141"]:
if EXCLUSIVE_MODE and chat_id not in EXCLUSIVE_LIST:
print(chat_id + " 为未认证群组,取消入库")
return
try:
username = update.effective_user.username
except Exception as e:
username = update.effective_user.id
user = update.message.from_user
firstname = str(user["first_name"])
lastname = str(user["last_name"])
name = ""
if firstname != "None":
name = firstname + " "
if lastname != "None":
name += lastname
if len(name) == 0:
name = username
name = firstname
print("\n---------------------------")
print("内容: " + text[:10])
print("群组类型: " + str(chat_type))
print("用户ID: " + str(user_id))
print("chat_id: " + str(chat_id))
if "/" in text:
print("这是一条指令信息,跳过")
if text.startwith('/') or '//' in text:
print("这是一条指令或者链接信息,跳过")
return
else:
if text[-1] not in ["", "", "", "", "", "!", "?", ",", ":", "."]:

126
images/README.md Normal file
View File

@ -0,0 +1,126 @@
## 当前版本
v2.3
## 更新维护日志
[更新维护日志](https://github.com/devourbots/word_cloud_bot/wiki/%E6%9B%B4%E6%96%B0%E7%BB%B4%E6%8A%A4%E6%97%A5%E5%BF%97)
## 有问题请加群组反馈
Telegram 交流反馈群组 [点击加入](https://t.me/devourbots)
## 演示
![xq9iR.png](https://s3.jpg.cm/2021/05/05/xq9iR.png)
## 配置要求
内存1G以上
## 安装方法
### 使用 Docker 安装
Docker官方安装地址[点击访问](https://docs.docker.com/engine/install/)
```angular2html
cd /root
# 拉取Redis镜像
docker pull redis
# 创建 entrypoint.sh 入口文件
echo '#! /bin/sh \
cd /root/word_cloud_bot && python3 main.py >> output 2>&1 &
tail -f /dev/null' > /root/entrypoint.sh
# 创建 Dockerfile
wget -O /root/Dockerfile https://github.com/devourbots/word_cloud_bot/raw/master/Dockerfile
# 使用命令查看所有时区
timedatectl list-timezones
找到您所在的时区,例如:
上海 Asia/Shanghai
纽约 America/New_York
# 编辑Dockerfile
vi /root/Dockerfile
# 在第7行修改服务器所属时区原文件为
RUN ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
修改为纽约当地时,修改后:
RUN ln -s /usr/share/zoneinfo/America/New_York /etc/localtime
# 在第10行修改你的机器人TOKEN
修改后:
RUN sed -i '1c TOKEN = "1749418611:AAGcpouQ4EWSDITLQXFozHjMgT_-MsVSmDM"' /root/word_cloud_bot/config.py
# 根据 Dockerfile 创建镜像
docker build . -t world_cloud_bot:latest
# 运行 Redis 镜像,此步在前
docker run -d -p 6379:6379 redis:latest
# 注意!!!
请关闭服务器 6379 端口的外网访问权限如果您的主机提供商提供了安全组策略阿里云、腾讯云、AWS等等可以在控制台关闭6379端口。
如果您的主机商不支持自定义安全组,请根据您的发行版系统自行搜索防火墙关闭端口的方式,检测方式在下方。
不要抱有侥幸心理!不要抱有侥幸心理!不要抱有侥幸心理!
# 运行 机器人,此步在后
docker run -d --net=host world_cloud_bot:latest
```
[端口检测工具](http://tool.chinaz.com/port/), 请确保 6379 是关闭状态
![xlu8H.png](https://s3.jpg.cm/2021/05/06/xlu8H.png)
## 使用方法
使用 `/start` 指令测试机器人与 Redis 数据库的连通情况
使用 `/rank` 指令主动触发词云任务,在 config.py 里可以设置每个群组每小时主动触发次数的限制
将机器人拉入群组设置为管理员受机器人API所限只有授予管理员权限后机器人才能接收到所有用户的普通聊天文本此机器人不需要其他权限您可以将所有权限关闭
所有聊天内容每天定时清理,仅用于本地分词,无其他任何用途
![xqyvt.png](https://s3.jpg.cm/2021/05/05/xqyvt.png)
### 将机器人设置为仅自己群组可用
如何编辑 Docker 容器中的文件请自行 Google
如果您不想让别人使用你的机器人,那么可以将 `config.py` 文件中的 `EXCLUSIVE_MODE = 0`改为 `EXCLUSIVE_MODE = 1`
![DGbSy.png](https://s3.jpg.cm/2021/05/09/DGbSy.png)
编辑 `/root/word_cloud_bot/func.py`,在 94 行左右,将自己的 群组ID 加入到列表中。
这里的`EXCLUSIVE_MODE = 1`不要改动,注意区分!
例如我两个的群组ID分别为-127892174935、-471892571924
那么修改后为:
```angular2html
if EXCLUSIVE_MODE == 1 and chat_id not in ["-127892174935", "-471892571924"]:
print(chat_id + " 为未认证群组,取消入库")
return
```
![DGHR5.png](https://s3.jpg.cm/2021/05/09/DGHR5.png)
### 设置 /rank 指令对普通用户开放
编辑 `/root/word_cloud_bot/config.py``RANK_COMMAND_MODE = 1` 改为 `RANK_COMMAND_MODE = 0`
![DGJuC.png](https://s3.jpg.cm/2021/05/09/DGJuC.png)
### 信息推送密度
![xW3jh.png](https://s3.jpg.cm/2021/05/05/xW3jh.png)
默认分别会在当地时间 11:00、18:00、23:30 推送三次数据统计报告,并会在 23:59 清空当日统计数据,
如需更密集的数据推送,可以编辑 /root/word_cloud_bot/main.py ,按照示例格式自行增加,相关的 docker 技术操作不再赘述

View File

@ -5,7 +5,8 @@ import schedule
from task import schedule_task, flush_redis, do_task
import threading
schedule.every().day.at('11:00').do(schedule_task)
# 开始定时任务 - 群组分析
schedule.every().day.at('12:00').do(schedule_task)
schedule.every().day.at('18:00').do(schedule_task)
schedule.every().day.at('23:30').do(schedule_task)
schedule.every().day.at('23:59').do(flush_redis)

105
task.py
View File

@ -8,7 +8,7 @@ import telegram
import time
import os
import connector
from config import TOKEN
from config import TOKEN, FRONT
bot = telegram.Bot(token=TOKEN)
@ -27,7 +27,7 @@ def schedule_task():
print("运行定时任务,让任务队列中添加任务,任务数量:{}".format(len(group_list)))
for group in group_list:
try:
# 任务队列中添加任务
# 任务队列中添加任务
task_queue.put(group)
except Exception as e:
print("群组:{} | 词云数据分析生成失败,请查看报错信息".format(group))
@ -61,12 +61,12 @@ def add_task(group):
# 核心函数,分词统计
def generate(group):
mk = imageio.imread("/root/word_cloud_bot/circle.png")
mk = imageio.imread("circle.png")
# 构建并配置词云对象w注意要加scale参数提高清晰度
w = wordcloud.WordCloud(width=800,
height=800,
background_color='white',
font_path='/root/word_cloud_bot/font.ttf',
font_path=FRONT,
mask=mk,
scale=5)
r = connector.get_connection()
@ -76,15 +76,7 @@ def generate(group):
chat_content = r.get("{}_chat_content".format(group))
if chat_content is None:
print("数据库中不存在此群组数据")
try:
time.sleep(1)
bot.send_message(
chat_id=group,
text="数据库中不存在群组数据,请检查是否授予机器人管理员权限,并通过聊天添加数据量,嗨起来吧~\n"
)
except Exception as e:
print("群组: {} | 机器人发送信息失败".format(group))
print("数据库中不存在此群组 {} 数据".format(group))
return
word_list = []
words = pseg.cut(chat_content, use_paddle=True) # paddle模式
@ -107,8 +99,8 @@ def generate(group):
user_message_amount = r.hgetall("{}_user_message_amount".format(group))
user_message_amount = sorted(user_message_amount.items(), key=lambda kv: (int(kv[1])), reverse=True)
# 分析高频词
if len(word_list) > 0:
# 分析高频词
word_amount = {}
# print(word_amount)
for word in word_list:
@ -128,77 +120,62 @@ def generate(group):
hot_word_string = ""
# 默认展示前5位少于5个则全部展示
for i in range(min(5, len(word_amount))):
hot_word_string += "\t\t\t\t\t\t\t\t" + "`" + str(word_amount[i][0]) + "`" + ": " + str(
hot_word_string += "\t\t\t\t\t\t\t\t" + "👥`" + str(word_amount[i][0]) + "`" + "" + str(
word_amount[i][1]) + "\n"
# print(hot_word_string)
bot.send_message(
chat_id=group,
text="🎤 今日话题榜 🎤\n"
"📅 {}\n"
"⏱ 截至今天{}\n"
"🗣️ 本群{}位朋友共产生{}条发言\n"
"🤹‍ 大家今天讨论最多的是:\n\n"
"{}\n"
"看下有没有你感兴趣的话题? 👏".format(
time.strftime("%Y年%m月%d", time.localtime()),
time.strftime("%H:%M", time.localtime()),
user_amount,
total_message_amount,
hot_word_string),
parse_mode="Markdown"
)
text = f"🗣️ 本群{user_amount}位朋友共产生{total_message_amount}条发言\n" \
f"🤹‍ 大家今天讨论最多的是:\n\n{hot_word_string}\n"
else:
text = '无法分析出当前群组的热词列表,可能是数据量过小,嗨起来吧~\n'
else:
bot.send_message(
chat_id=group,
text="当前聊天数据量过小,嗨起来吧~"
)
text = '无法分析出当前群组的热词列表,可能是数据量过小,嗨起来吧~\n'
# 分析活跃用户
if len(user_message_amount) > 0:
# print("排序后的用户:" + str(user_message_amount))
top_5_user = ""
# 默认展示前5位少于5个则全部展示
for i in range(min(5, len(user_message_amount))):
dis_name = str(user_message_amount[i][0])
top_5_user += "\t\t\t\t\t\t\t\t" + "🎖`" + dis_name[:min(8, len(dis_name))] + "`" + " 贡献: " + str(
top_5_user += "\t\t\t\t\t\t\t\t" + "🎖`" + dis_name[:min(8, len(dis_name))] + "`" + " 贡献:" + str(
user_message_amount[i][1]) + "\n"
# print(top_5_user)
bot.send_message(
chat_id=group,
text="🏵 今日活跃用户排行榜 🏵\n"
"📅 {}\n"
"⏱ 截至今天{}\n\n"
"{}\n"
"感谢这些朋友今天的分享! 👏 \n"
"遇到问题,向他们请教说不定有惊喜😃".format(
time.strftime("%Y年%m月%d", time.localtime()),
time.strftime("%H:%M", time.localtime()),
top_5_user),
parse_mode="Markdown"
)
text += f"🏵 今日活跃用户排行榜 🏵\n\n{top_5_user}"
else:
bot.send_message(
chat_id=group,
text="当前聊天数据量过小,嗨起来吧~"
)
text = '无法分析出当前群组的活跃用户列表,可能是数据量过小,嗨起来吧~'
# 开始创建词云
img_path = 'images/default.png'
try:
string = " ".join(word_list)
# 将string变量传入w的generate()方法,给词云输入文字
w.generate(string)
# 将词云图片导出到当前文件夹
w.to_file('{}_chat_word_cloud.png'.format(group))
bot.send_photo(
chat_id=group,
photo=open("{}_chat_word_cloud.png".format(group), "rb")
)
os.remove("{}_chat_word_cloud.png".format(group))
# 将词云图片导出到 images 文件夹
w.to_file('images/{}_chat_word_cloud.png'.format(group))
img_path = 'images/{}_chat_word_cloud.png'.format(group)
except Exception as e:
print(e)
print("词云图片生成失败")
# bot.send_message(
# chat_id=group,
# text="当前聊天数据量过小,嗨起来吧~"
# )
# 发送结果
try:
bot.send_photo(
chat_id=group,
photo=open(img_path, "rb"),
caption=text,
parse_mode='markdown',
disable_notification=True
)
except Exception as e:
print(e)
print("发送结果失败")
# 删除图片
try:
os.remove("images/{}_chat_word_cloud.png".format(group))
except Exception as e:
print(e)
print("删除图片失败")
def flush_redis():