Compare commits

...

26 Commits

Author SHA1 Message Date
luming
ba170eb3d7 fix admin chat error
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/tag Build is failing
2021-05-19 16:04:28 +08:00
bdfcd71fdb
Update .drone.yml
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/tag Build is failing
2021-03-24 18:51:30 +08:00
7feaea08da
Update .drone.yml 2021-03-24 18:30:47 +08:00
f068f53112
Update .drone.yml 2021-03-24 18:29:21 +08:00
628373ce58
Create .drone.yml 2021-03-24 17:39:18 +08:00
64bd4d68f7 📝 update document. 2021-01-18 16:50:13 +08:00
5a5c24eeaf Modify configuration file.
Add a language item.
2021-01-18 14:22:58 +08:00
ad4b39d8dd add systemd unit file. 2021-01-17 18:45:28 +08:00
rainerosion
5f98f4de29 🌐 Modify link 2020-12-28 23:27:21 +08:00
rainerosion
6384d46dad 📝 update documents 2020-12-27 00:17:41 +08:00
rainerosion
1084e1814a 📝 update documents 2020-12-17 21:07:09 +08:00
rainerosion
4095894f89 📝 update documents 2020-12-16 19:51:42 +08:00
rainerosion
e62bd1f2f5 📝 add language 2020-12-16 02:27:51 +08:00
rainerosion
c9ccc82b71 🌐 add language 2020-12-16 01:40:47 +08:00
rainerosion
4f7ee0abff 🌐 add language 2020-12-16 01:24:37 +08:00
rainerosion
3d5f1378fd 📝 Writing documents 2020-12-15 14:19:18 +08:00
rainerosion
d8b13d6d35 add Dockerfile 2020-12-15 14:04:45 +08:00
rainerosion
f08aa5b2cb :docs: Update document 2020-12-15 03:22:34 +08:00
rainerosion
d901e25faf Merge remote-tracking branch 'origin/master' 2020-12-15 03:09:14 +08:00
rainerosion
cb773010eb :docs: Add docker deployment 2020-12-15 03:08:49 +08:00
74d7484a0a
Update config.yml.example 2020-12-15 01:10:54 +08:00
rainerosion
3b0331c3a6 :docs: Modify link 2020-12-14 00:06:16 +08:00
rainerosion
5739408410 :docs: Convert data from mysql to sqlite 2020-12-14 00:05:29 +08:00
rainerosion
9c4d3f3c78 :docs: Convert data from mysql to sqlite 2020-12-14 00:04:30 +08:00
rainerosion
5e28904491 :docs: Add english document 2020-12-13 22:50:01 +08:00
rainerosion
ef8bfd1f8e :docs: Add Chinese document 2020-12-13 22:33:39 +08:00
11 changed files with 740 additions and 63 deletions

9
.drone.yml Normal file
View File

@ -0,0 +1,9 @@
kind: pipeline
type: docker
name: E5SubBotForSQLite
steps:
- name: gobuild
image: golang:alpine
pull: if-not-exists
commands:
- CGO_ENABLED=1 go build

20
Dockerfile Normal file
View File

@ -0,0 +1,20 @@
FROM golang:alpine AS builder
WORKDIR /root
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && apk update && apk add git gcc g++\
&& git clone https://github.com/rainerosion/E5SubBot.git \
&& cd E5SubBot && GOPROXY=https://goproxy.cn,direct CGO_ENABLED=1 go build
FROM alpine:latest
ENV TIME_ZONE=Asia/Shanghai
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && apk update && apk add tzdata \
&& ln -snf /usr/share/zoneinfo/$TIME_ZONE /etc/localtime && echo $TIME_ZONE > /etc/timezone
WORKDIR /root
COPY --from=builder /root/E5SubBot/main /root
CMD [ "/root/main" ]

207
README.md Normal file
View File

@ -0,0 +1,207 @@
# E5SubBot For SQLite
![](https://img.shields.io/github/go-mod/go-version/rainerosion/E5SubBot?style=flat-square)
![](https://img.shields.io/badge/license-GPL-lightgrey.svg?style=flat-square)
![](https://img.shields.io/github/v/release/rainerosion/E5SubBot?color=green&style=flat-square)
English | [简体中文](https://github.com/rainerosion/E5SubBot/blob/master/README_zhCN.md)
A Simple Telebot for E5 Renewal
`Golang` + `SQLite`
DEMO: https://t.me/raindev_bot (This DEMO is agesor testing only)
Communication: [Telegram Group](https://t.me/e5subbot)
## Introduction
The project was modified from [iyear/E5SubBot](https://github.com/iyear/E5SubBot).
## Feature
- Automatically Renew E5 Subscription(Customizable Frequency)
- Manageable Simple Account System
- Available Task Execution Feedback
- Convenient Authorization
## Principle
E5 subscription is a subscription for developers, as long as the related API is called, it may be renewed
Calling [Outlook ReadMail API](https://docs.microsoft.com/en-us/graph/api/user-list-messages?view=graph-rest-1.0&tabs=http) to renew, does not guarantee the renewal effect.
## Usage
1. Type `/bind` in the robot dialog
2. Click the link sent by the robot and register the Microsoft application, log in with the E5 master account or the same domain account, and obtain `client_secret`. **Click to go back to Quick Start**, get `client_id`
3. Copy `client_secret` and `client_id` and reply to bot in the format of `client_id(space)client_secret`
(Pay attention to spaces)
4. Click on the authorization link sent by the robot and log in with the `E5` master account or the same domain account
5. After authorization, it will jump to `http://localhost/e5sub……` (will prompt webpage error, just copy the link)
6. Copy the link, and reply `link(space)alias (used to manage accounts)` in the robot dialog
For example: `http://localhost/e5sub/?code=abcd MyE5`, wait for the robot to bind and then complete
## Deploy Your Own Bot
Bot creation tutorial : [Microsoft](https://docs.microsoft.com/en-us/azure/bot-service/bot-service-channel-connect-telegram?view=azure-bot-service-4.0)
### Docker
```bash
mkdir /opt/e5sub
# (important)Create database file
touch /opt/e5sub/e5sub.db
wget --no-check-certificate -O /opt/e5sub/config.yml https://raw.githubusercontent.com/rainerosion/E5SubBotForSQLite/master/config.yml.example
# Modify configuration file
vim /opt/e5sub/config.yml
docker run -d -v /opt/e5sub/config.yml:/root/config.yml -v /opt/e5sub/e5sub.db:/root/e5sub.db --restart=always --name e5bot rainerosion/e5subbot-sqlite
```
### Binary Deployment
Download the binary files of the corresponding system on the [Releases](https://github.com/rainerosion/E5SubBotForSQLite/releases) page and upload it to the server
Windows: Start `E5SubBot.exe` in `cmd`
Linux:
```bash
chmod a+x E5SubBot
nohup ./E5SubBot > /tmp/e5sub.log &
```
Linux Systemd:
- download file
```bash
wget https://github.com/rainerosion/E5SubBotForSQLite/releases/download/0.2.2/E5SubBot-linux-amd64.tar.gz
# Unzip file
tar xvjf E5SubBot_linux_x64.tar.gz
# create folder
mkdir /opt/e5sub
# Move file
mv ./E5SubBot /opt/e5sub/E5SubBot
# Add execution permission
chmod a+x /opt/e5sub/E5SubBot
# Modify configuration file
vim /opt/e5sub/config.yml
# Download Systemd unit file
sudo wget -O /etc/systemd/system/e5sub.service https://raw.githubusercontent.com/rainerosion/E5SubBotForSQLite/master/e5sub.service
```
- Start service
```bash
# Load configuration file
systemctl daemon-reload
# Start up automatically
systemctl enable e5sub
# Start service
systemctl start e5sub
```
### Compile
Download the source code and install the GO environment
```shell
go env -w CGO_ENABLED=1
go build
```
## Configuration
Create `config.yml` in the same directory, encoded as `UTF-8`
Configuration Template:
```yaml
bot_token: YOUR_BOT_TOKEN
socks5: 127.0.0.1:1080
notice: "first line\nsecond line"
admin: 66666,77777,88888
errlimit: 5
cron: "1 */3 * * *"
bindmax: 3
dbfile: "e5sub.db"
lang: zh_CN
```
`bindmax`, `notice`, `admin`, `errlimit` can be hot updated, just update `config.yml` to save.
| Configuration | Explanation|
| ---- | ---- |
| bot_token | Change to your own `BotToken` |
| socks5 | `Socks5` proxy,if you do not need ,you should delete it. For example: `127.0.0.1:1080` |
|notice|Announcement. Merged into `/help`|
|admin|The administrator's `tgid`, go to https://t.me/userinfobot to get it, separated by `,`; Administrator permissions: manually call the task, get the total feedback of the task|
|errlimit|The maximum number of errors for a single account, automatically unbind the single account and send a notification when it is full, without limiting the number of errors, change the value to a negative number `(-1)`; all errors will be cleared after the bot restarts|
|cron|API call frequency, using `cron` expression|
|bindmax|Maximum number of bindable|
|dbfile|Database file|
|lang|Simplified Chinese(default)`zh_CN` English:`en_US`|
### Command
```
/my View bound account information
/bind Bind new account
/unbind Unbind account
/export Export account information (JSON format)
/help help
/task Manually execute a task (Bot Administrator)
/log Get the most recent log file (Bot Administrator)
```
## Convert data from mysql to sqlite
If this command does not exist on your operating system.
```bash
# Centos
sudo yum install sqlite
# Archlinux
sudo pacman -S sqlite3
# Ubuntu
sudo apt-get install sqlite3
```
Export data
```bash
# Export MYSQL data
mysqldump -h localhost -P 3306 -u root -p -t dbname users > e5sub.sql
# Filtering data
grep "INSERT" e5sub.sql > e5sqlite.sql
# Open sqlite database
sqlite3 /opt/e5sub/e5sub.db
# Create table and import data.
sqlite3> CREATE TABLE `users` (
`tg_id` int(11) DEFAULT NULL,
`refresh_token` text,
`ms_id` varchar(255) DEFAULT NULL,
`uptime` int(11) DEFAULT NULL,
`alias` varchar(255) DEFAULT NULL,
`client_id` varchar(255) DEFAULT NULL,
`client_secret` varchar(255) DEFAULT NULL,
`other` text);
sqlite3> .read e5sqlite.sql
sqlite3> .quit
# Delete file
rm -f e5sqlite.sql e5sub.sql
```
## Others
> Feedback time is not as expected
Change the server time zone, use `/task` to manually perform a task to refresh time.
> Long running crash
Suspected memory leak. Not yet resolved, please run the daemon or restart Bot regularly.
> Unable to create application via bot
https://t.me/e5subbot/5201
## License
GPLv3

203
README_zhCN.md Normal file
View File

@ -0,0 +1,203 @@
# E5SubBot For SQLite
![](https://img.shields.io/github/go-mod/go-version/rainerosion/E5SubBot?style=flat-square)
![](https://img.shields.io/badge/license-GPL-lightgrey.svg?style=flat-square)
![](https://img.shields.io/github/v/release/rainerosion/E5SubBot?color=green&style=flat-square)
[English](https://github.com/rainerosion/E5SubBot) | 简体中文
A Simple Telebot for E5 Renewal
`Golang` + `SQLite`
DEMO: https://t.me/raindev_bot (仅用于测试DEMO测试)
[e5subbot交流群组](https://t.me/e5subbot)
## 说明
该项目是基于[iyear/E5SubBot](https://github.com/iyear/E5SubBot)进行简单的修改,将`github.com/go-sql-driver/mysql`替换为`github.com/mattn/go-sqlite3`实现使用SQLite数据库保存数据的。
## 特性
- 自动续订E5订阅(可自定义的调用频率)
- 可管理的简易账户系统
- 完善的任务执行反馈
- 极为方便的授权方式
## 原理
E5订阅为开发者订阅只要调用相关API就有可能续期
调用 [Outlook ReadMail API](https://docs.microsoft.com/zh-cn/graph/api/user-list-messages?view=graph-rest-1.0&tabs=http) 实现玄学的续订方式,不保证续订效果。
## 使用方法
1. 在机器人对话框输入 **/bind**
2. 注册应用使用E5主账号或同域账号登录跳转页面获得client_secret。**点击回到快速启动**,获得client_id
3. 复制client_secret和client_id`client_id client_secret`格式回复
4. 获得授权链接使用E5主账号或同域账号登录
5. 授权后会跳转至`http://localhost/e5sub……` (会提示网页错误,复制链接即可)
6. 复制整个浏览框内容,在机器人对话框回复 `链接+空格+别名(用于管理账户)`
例如:`http://localhost/e5sub/?code=abcd MyE5`,等待机器人绑定后即完成
## 自行部署
Bot创建教程:[Google](https://www.google.com/search?q=telegram+Bot%E5%88%9B%E5%BB%BA%E6%95%99%E7%A8%8B)
### Docker部署
```bash
mkdir /opt/e5sub
# (重要)创建数据库文件
touch /opt/e5sub/e5sub.db
wget --no-check-certificate -O /opt/e5sub/config.yml https://raw.githubusercontent.com/rainerosion/E5SubBotForSQLite/master/config.yml.example
# 修改配置文件中的信息
vim /opt/e5sub/config.yml
docker run -d -v /opt/e5sub/config.yml:/root/config.yml -v /opt/e5sub/e5sub.db:/root/e5sub.db --restart=always --name e5bot rainerosion/e5subbot-sqlite
```
### 二进制文件
在[Releases](https://github.com/rainerosion/E5SubBotForSQLite/releases)页面下载对应系统的二进制文件,上传至服务器
Windows: 在`cmd`中启动 `E5SubBot.exe`
Linux(方法一):
```bash
chmod a+x E5SubBot
nohup ./E5SubBot > /tmp/e5sub.log &
```
Linux守护进程(Systemd)
- 下载相关文件
```bash
wget https://github.com/rainerosion/E5SubBotForSQLite/releases/download/0.2.2/E5SubBot-linux-amd64.tar.gz
# 解压文件
tar xvjf E5SubBot_linux_x64.tar.gz
# 创建文件夹
mkdir /opt/e5sub
# 移动文件
mv ./E5SubBot /opt/e5sub/E5SubBot
# 添加执行权限
chmod a+x /opt/e5sub/E5SubBot
# 编辑配置文件(文件内容请阅读部署配置)
vim /opt/e5sub/config.yml
# 下载Systemd unit文件
sudo wget -O /etc/systemd/system/e5sub.service https://raw.githubusercontent.com/rainerosion/E5SubBotForSQLite/master/e5sub.service
```
- 重载配置启动服务
```bash
# 重载配置文件
systemctl daemon-reload
# 开机自启
systemctl enable e5sub
# 启动服务
systemctl start e5sub
```
### 编译
若你的系统无法正常运行请clone源代码进行编译需要先安装GO环境
```shell
go env -w CGO_ENABLED=1
go build
```
## 部署配置
在同目录下创建`config.yml`,编码为`UTF-8`
配置模板:
```yaml
bot_token: YOUR_BOT_TOKEN
socks5: 127.0.0.1:1080
notice: "第一行\n第二行"
admin: 66666,77777,88888
errlimit: 5
cron: "1 */3 * * *"
bindmax: 3
dbfile: "e5sub.db"
lang: zh_CN
```
`bindmax`,`notice`,`admin`,`errlimit`可热更新,直接更新`config.yml`保存即可
| 配置项 | 说明 |
| ---- | ---- |
| bot_token | 更换为自己的`BotToken` |
| socks5 | `Socks5`代理,不需要删去即可.例如:`127.0.0.1:1080` |
|notice|公告.合并至`/help`|
|admin|管理员`tgid`,前往 https://t.me/userinfobot 获取,用`,`隔开;管理员权限: 手动调用任务,获得任务总反馈|
|errlimit|单账户最大出错次数,满后自动解绑单账户并发送通知,不限制错误次数将值改为负数`(-1)`即可;bot重启后会清零所有错误次数|
|cron|API调用频率使用cron表达式|
|bindmax|最大可绑定数|
|dbfile|sqlite数据库文件名|
|lang|简体中文(默认)`zh_CN` English:`en_US`|
### 命令
```
/my 查看已绑定账户信息
/bind 绑定新账户
/unbind 解绑账户
/export 导出账户信息(JSON格式)
/help 帮助
/task 手动执行一次任务(Bot管理员)
/log 获取最近日志文件(Bot管理员)
```
## MYSQL数据库转SQLITE
如果没有sqlite3命令请使用下列命令安装
```bash
sudo yum install sqlite -y
```
导出数据
```bash
# 导出mysql数据
mysqldump -h localhost -P 3306 -u root -p -t 数据库名 users > e5sub.sql
# 过滤数据
grep "INSERT" e5sub.sql > e5sqlite.sql
# 使用sqlite3打开数据库文件
sqlite3 /opt/e5sub/e5sub.db
# 创建表,导入数据
sqlite3> CREATE TABLE `users` (
`tg_id` int(11) DEFAULT NULL,
`refresh_token` text,
`ms_id` varchar(255) DEFAULT NULL,
`uptime` int(11) DEFAULT NULL,
`alias` varchar(255) DEFAULT NULL,
`client_id` varchar(255) DEFAULT NULL,
`client_secret` varchar(255) DEFAULT NULL,
`other` text);
sqlite3> .read e5sqlite.sql
sqlite3> .quit
# 清除文件
rm -f e5sqlite.sql e5sub.sql
```
## 注意事项
> 更新时间与北京时间不符
更改服务器时区为`Asia/Shanghai`,然后使用`/task`手动执行一次任务刷新时间
> 绑定格式错误
不要带"+"号
> 长时间运行崩溃
疑似内存泄露,尚未解决,请自行采用守护进程运行或定时重启`Bot`
> 无法通过Bot创建应用程序
https://t.me/e5subbot/5201
## License
GPLv3

View File

@ -1,9 +1,9 @@
bot_token: xxx
#socks5: 127.0.0.1:1080
bindmax: 3
admin: 555,666,777
bot_token: YOUR_BOT_TOKEN
socks5: 127.0.0.1:1080
notice: "first line\nsecond line"
admin: 66666,77777,88888
errlimit: 5
notice: "aaa\nbbb"
cron: "1 */3 * * *"
#以下是SQLite数据库名称
bindmax: 3
dbfile: "e5sub.db"
lang: zh_CN

View File

@ -3,6 +3,7 @@ package main
import (
"errors"
"fmt"
"github.com/chai2010/gettext-go"
"github.com/spf13/viper"
"github.com/tidwall/gjson"
tb "gopkg.in/tucnak/telebot.v2"
@ -22,7 +23,7 @@ func BindUser(m *tb.Message, cid, cse string) error {
tmp := strings.Split(m.Text, " ")
if len(tmp) != 2 {
logger.Printf("%d Bind error:Wrong Bind Format\n", m.Chat.ID)
return errors.New("绑定格式错误")
return errors.New(gettext.Gettext("bindFormatError"))
}
logger.Println("alias: " + tmp[1])
alias := tmp[1]
@ -35,7 +36,7 @@ func BindUser(m *tb.Message, cid, cse string) error {
}
//token has gotten
bot.Send(m.Chat, "Token获取成功!")
bot.Send(m.Chat, gettext.Gettext("getToken"))
info, err := MSGetUserInfo(access)
//fmt.Printf("TGID:%d Refresh Token: %s\n", m.Chat.ID, refresh)
if err != nil {
@ -57,7 +58,7 @@ func BindUser(m *tb.Message, cid, cse string) error {
//MS User Is Exist
if MSAppIsExist(u.tgId, u.clientId) {
logger.Printf("%d Bind error:MSUserHasExisted\n", m.Chat.ID)
return errors.New("该应用已经绑定过了,无需重复绑定")
return errors.New(gettext.Gettext("alreadyBind"))
}
//MS information has gotten
bot.Send(m.Chat, "MS_ID(MD5) "+u.msId+"\nuserPrincipalName "+gjson.Get(info, "userPrincipalName").String()+"\ndisplayName "+gjson.Get(info, "displayName").String()+"\n")
@ -103,7 +104,7 @@ func SignTask() {
fmt.Println("Start Sign")
//签到任务
for _, u := range data {
pre := "您的账户: " + u.alias + "\n在任务执行时出现了错误!\n错误:"
pre := fmt.Sprintf(gettext.Gettext("taskError"), u.alias)
chat, err := bot.ChatByID(strconv.FormatInt(u.tgId, 10))
if err != nil {
logger.Println(err)
@ -111,7 +112,7 @@ func SignTask() {
}
//生成解绑按钮
var inlineKeys [][]tb.InlineButton
UnBindBtn := tb.InlineButton{Unique: "un" + u.msId, Text: "点击解绑该账户", Data: u.msId}
UnBindBtn := tb.InlineButton{Unique: "un" + u.msId, Text: gettext.Gettext("clickToUnBind"), Data: u.msId}
bot.Handle(&UnBindBtn, bUnBindInlineBtn)
inlineKeys = append(inlineKeys, []tb.InlineButton{UnBindBtn})
tmpBtn := &tb.ReplyMarkup{InlineKeyboard: inlineKeys}
@ -163,7 +164,7 @@ func SignTask() {
logger.Println(err)
} else {
UnbindUser = append(UnbindUser, u.msId+" ( @"+chat.Username+" )")
_, err = bot.Send(chat, "您的账户因达到错误上限而被自动解绑\n后会有期!\n\n别名: "+u.alias+"\nclient_id: "+u.clientId+"\nclient_secret: "+u.clientSecret)
_, err = bot.Send(chat, gettext.Gettext("unBindByMaxLimit")+u.alias+"\nclient_id: "+u.clientId+"\nclient_secret: "+u.clientSecret)
if err != nil {
logger.Println(err)
}
@ -172,7 +173,7 @@ func SignTask() {
}
if !isSend[u.tgId] {
//静默发送,过多消息很烦
_, err = bot.Send(chat, "任务反馈\n时间: "+time.Now().Format("2006-01-02 15:04:05")+"\n结果: "+strconv.Itoa(SignOk[u.tgId])+"/"+strconv.Itoa(GetBindNum(u.tgId)), &tb.SendOptions{DisableNotification: true})
_, err = bot.Send(chat, gettext.Gettext("taskFeedback")+time.Now().Format("2006-01-02 15:04:05")+gettext.Gettext("result")+strconv.Itoa(SignOk[u.tgId])+"/"+strconv.Itoa(GetBindNum(u.tgId)), &tb.SendOptions{DisableNotification: true})
if err != nil {
logger.Println(err)
}
@ -189,8 +190,12 @@ func SignTask() {
UnbindUserStr = UnbindUserStr + ubu + "\n"
}
for _, a := range admin {
chat, _ := bot.ChatByID(strconv.FormatInt(a, 10))
bot.Send(chat, "任务反馈(管理员)\n完成时间: "+time.Now().Format("2006-01-02 15:04:05")+"\n结果: "+strconv.Itoa(signOk)+"/"+strconv.Itoa(num)+"\n错误账户:\n"+ErrUserStr+"\n清退账户:\n"+UnbindUserStr)
chat, err := bot.ChatByID(strconv.FormatInt(a, 10))
if err != nil {
logger.Println(err)
continue
}
bot.Send(chat, gettext.Gettext("taskFeedbackAdmin")+time.Now().Format("2006-01-02 15:04:05")+gettext.Gettext("result")+strconv.Itoa(signOk)+"/"+strconv.Itoa(num)+gettext.Gettext("wrongAccount")+ErrUserStr+gettext.Gettext("clearingAccount")+UnbindUserStr)
}
fmt.Println("----Task End----")
}

12
e5sub.service Normal file
View File

@ -0,0 +1,12 @@
[Unit]
Description=Telegram E5Sub Bot
[Service]
Type=simple
WorkingDirectory=/opt/e5sub
ExecStart=/opt/e5sub/E5SubBot
Restart=always
RestartSec=30
[Install]
WantedBy=multi-user.target

3
go.mod
View File

@ -3,12 +3,13 @@ module main
go 1.13
require (
github.com/chai2010/gettext-go v1.0.2
github.com/fsnotify/fsnotify v1.4.7
github.com/mattn/go-sqlite3 v1.14.5
github.com/robfig/cron/v3 v3.0.0
github.com/spf13/viper v1.6.2
github.com/tidwall/gjson v1.6.0
github.com/tidwall/pretty v1.0.1 // indirect
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e
gopkg.in/tucnak/telebot.v2 v2.0.0-20200328014118-dd123e949ee1
github.com/mattn/go-sqlite3 v1.14.5
)

4
go.sum
View File

@ -8,6 +8,8 @@ github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk=
github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
@ -24,8 +26,6 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=

View File

@ -2,6 +2,7 @@ package main
import (
"encoding/json"
"github.com/chai2010/gettext-go"
"github.com/fsnotify/fsnotify"
"github.com/spf13/viper"
tb "gopkg.in/tucnak/telebot.v2"
@ -14,31 +15,20 @@ import (
)
const (
bLogBasePath string = "./log/"
bStartContent string = "欢迎使用E5SubBot!"
bHelpContent string = `
命令
/my 查看已绑定账户信息
/bind 绑定新账户
/unbind 解绑账户
/export 导出账户信息(JSON格式)
/help 帮助
/task 手动执行一次任务(管理员)
/log 获取最近日志文件(管理员)
源代码https://github.com/rainerosion/E5SubBot
原作者https://github.com/iyear/E5SubBot
`
bLogBasePath string = "./log/"
)
var (
UserStatus map[int64]int
UserCid map[int64]string
UserCSecret map[int64]string
ErrorTimes map[string]int //错误次数
BindMaxNum int
ErrMaxTimes int
notice string
admin []int64
UserStatus map[int64]int
UserCid map[int64]string
UserCSecret map[int64]string
ErrorTimes map[string]int //错误次数
BindMaxNum int
ErrMaxTimes int
notice string
admin []int64
bStartContent string
bHelpContent string
)
const (
@ -56,6 +46,16 @@ func init() {
viper.SetDefault("errlimit", 5)
viper.SetDefault("bindmax", 5)
viper.SetDefault("bindmax", 5)
viper.SetDefault("lang", "zh_CN")
//set language
gettext.BindLocale(gettext.New("resources", "???", jsonData))
lang := strings.Trim(viper.GetString("lang"), "")
gettext.SetLanguage(lang)
bStartContent = gettext.Gettext("welcome")
bHelpContent = gettext.Gettext("helpContent")
BindMaxNum = viper.GetInt("bindmax")
ErrMaxTimes = viper.GetInt("errlimit")
@ -94,21 +94,21 @@ func bMy(m *tb.Message) {
bot.Handle(&inlineBtn, bMyInlineBtn)
inlineKeys = append(inlineKeys, []tb.InlineButton{inlineBtn})
}
bot.Send(m.Chat, "选择一个账户查看具体信息\n\n绑定数: "+strconv.Itoa(GetBindNum(m.Chat.ID))+"/"+strconv.Itoa(BindMaxNum), &tb.ReplyMarkup{InlineKeyboard: inlineKeys})
bot.Send(m.Chat, gettext.Gettext("chooseAnAccount")+strconv.Itoa(GetBindNum(m.Chat.ID))+"/"+strconv.Itoa(BindMaxNum), &tb.ReplyMarkup{InlineKeyboard: inlineKeys})
}
func bMyInlineBtn(c *tb.Callback) {
logger.Println(strconv.FormatInt(c.Message.Chat.ID, 10) + " Get User Info")
r := QueryDataByMS(c.Data)
u := r[0]
bot.Send(c.Message.Chat, "信息\n别名"+u.alias+"\nMS_ID(MD5): "+u.msId+"\nclient_id: "+u.clientId+"\nclient_secret: "+u.clientSecret+"\n最近更新时间: "+time.Unix(u.uptime, 0).Format("2006-01-02 15:04:05"))
bot.Send(c.Message.Chat, gettext.Gettext("accountInformation")+u.alias+"\nMS_ID(MD5): "+u.msId+"\nclient_id: "+u.clientId+"\nclient_secret: "+u.clientSecret+gettext.Gettext("updateTime")+time.Unix(u.uptime, 0).Format("2006-01-02 15:04:05"))
bot.Respond(c)
}
func bBind1(m *tb.Message) {
logger.Println(strconv.FormatInt(m.Chat.ID, 10) + " Start Bind")
logger.Println("ReApp: " + strconv.FormatInt(m.Chat.ID, 10))
bot.Send(m.Chat, "应用注册: [点击直达]("+MSGetReAppUrl()+")", tb.ModeMarkdown)
_, err := bot.Send(m.Chat, "请回复client_id+空格+client_secret", &tb.ReplyMarkup{ForceReply: true})
bot.Send(m.Chat, gettext.Gettext("register")+"("+MSGetReAppUrl()+")", tb.ModeMarkdown)
_, err := bot.Send(m.Chat, gettext.Gettext("bind1Reply"), &tb.ReplyMarkup{ForceReply: true})
if err != nil {
logger.Println(err)
return
@ -122,14 +122,14 @@ func bBind2(m *tb.Message) {
tmp := strings.Split(m.Text, " ")
if len(tmp) != 2 {
logger.Printf("%d Bind error:Wrong Bind Format\n", m.Chat.ID)
bot.Send(m.Chat, "错误的格式")
bot.Send(m.Chat, gettext.Gettext("formatError"))
return
}
logger.Println("client_id: " + tmp[0] + " client_secret: " + tmp[1])
cid := tmp[0]
cse := tmp[1]
bot.Send(m.Chat, "授权账户: [点击直达]("+MSGetAuthUrl(cid)+")", tb.ModeMarkdown)
_, err := bot.Send(m.Chat, "请回复http://localhost/…… + 空格 + 别名(用于管理)", &tb.ReplyMarkup{ForceReply: true})
bot.Send(m.Chat, gettext.Gettext("signIn")+"("+MSGetAuthUrl(cid)+")", tb.ModeMarkdown)
_, err := bot.Send(m.Chat, gettext.Gettext("bind2Reply"), &tb.ReplyMarkup{ForceReply: true})
if err != nil {
logger.Println(err)
return
@ -152,7 +152,7 @@ func bUnBind(m *tb.Message) {
bot.Handle(&inlineBtn, bUnBindInlineBtn)
inlineKeys = append(inlineKeys, []tb.InlineButton{inlineBtn})
}
bot.Send(m.Chat, "选择一个账户将其解绑\n\n当前绑定数: "+strconv.Itoa(GetBindNum(m.Chat.ID))+"/"+strconv.Itoa(BindMaxNum), &tb.ReplyMarkup{InlineKeyboard: inlineKeys})
bot.Send(m.Chat, gettext.Gettext("unBind")+strconv.Itoa(GetBindNum(m.Chat.ID))+"/"+strconv.Itoa(BindMaxNum), &tb.ReplyMarkup{InlineKeyboard: inlineKeys})
}
func bUnBindInlineBtn(c *tb.Callback) {
logger.Println(strconv.FormatInt(c.Message.Chat.ID, 10) + " Unbind: " + c.Data)
@ -160,11 +160,11 @@ func bUnBindInlineBtn(c *tb.Callback) {
u := r[0]
if ok, _ := DelData(u.msId); !ok {
logger.Println(u.msId + " UnBind ERROR")
bot.Send(c.Message.Chat, "解绑失败!")
bot.Send(c.Message.Chat, gettext.Gettext("unBindError"))
return
}
logger.Println(u.msId + " UnBind Success")
bot.Send(c.Message.Chat, "解绑成功!")
bot.Send(c.Message.Chat, gettext.Gettext("unBindSuccess"))
bot.Respond(c)
}
func bExport(m *tb.Message) {
@ -179,7 +179,7 @@ func bExport(m *tb.Message) {
var MsMini []MsMiniData
data := QueryDataByTG(m.Chat.ID)
if len(data) == 0 {
bot.Send(m.Chat, "你还没有绑定过账户嗷~")
bot.Send(m.Chat, gettext.Gettext("unbound"))
return
}
for _, u := range data {
@ -195,14 +195,14 @@ func bExport(m *tb.Message) {
export, err := json.MarshalIndent(MsMini, "", "\t")
if err != nil {
logger.Println(err)
bot.Send(m.Chat, "获取JSON失败~\n"+err.Error())
bot.Send(m.Chat, gettext.Gettext("json")+err.Error())
return
}
//fmt.Println(string(export))
fileName := "./" + strconv.FormatInt(m.Chat.ID, 10) + "_export_tmp.json"
if err = ioutil.WriteFile(fileName, export, 0644); err != nil {
logger.Println(err)
bot.Send(m.Chat, "写入临时文件失败~\n"+err.Error())
bot.Send(m.Chat, gettext.Gettext("temporary")+err.Error())
return
}
exportFile := &tb.Document{File: tb.FromDisk(fileName), FileName: strconv.FormatInt(m.Chat.ID, 10) + ".json", MIME: "text/plain"}
@ -225,13 +225,13 @@ func bOnText(m *tb.Message) {
switch UserStatus[m.Chat.ID] {
case USNone:
{
bot.Send(m.Chat, "发送/help获取帮助嗷")
bot.Send(m.Chat, gettext.Gettext("getHelp"))
return
}
case USBind1:
{
if !m.IsReply() {
bot.Send(m.Chat, "请通过回复方式绑定")
bot.Send(m.Chat, gettext.Gettext("replyBind"))
return
}
bBind2(m)
@ -239,19 +239,19 @@ func bOnText(m *tb.Message) {
case USBind2:
{
if !m.IsReply() {
bot.Send(m.Chat, "请通过回复方式绑定")
bot.Send(m.Chat, gettext.Gettext("replyBind"))
return
}
if GetBindNum(m.Chat.ID) == BindMaxNum {
bot.Send(m.Chat, "已经达到最大可绑定数")
bot.Send(m.Chat, gettext.Gettext("maximum"))
return
}
bot.Send(m.Chat, "正在绑定中……")
bot.Send(m.Chat, gettext.Gettext("binding"))
err := BindUser(m, UserCid[m.Chat.ID], UserCSecret[m.Chat.ID])
if err != nil {
bot.Send(m.Chat, err.Error())
} else {
bot.Send(m.Chat, "绑定成功!")
bot.Send(m.Chat, gettext.Gettext("bindSuccess"))
}
UserStatus[m.Chat.ID] = USNone
}
@ -265,7 +265,7 @@ func bTask(m *tb.Message) {
return
}
}
bot.Send(m.Chat, "您没有权限执行此操作~")
bot.Send(m.Chat, gettext.Gettext("noPermission"))
}
func bLog(m *tb.Message) {
logger.Println(strconv.FormatInt(m.Chat.ID, 10) + " Start Get Logs")
@ -276,7 +276,7 @@ func bLog(m *tb.Message) {
}
}
if flag == 0 {
bot.Send(m.Chat, "您没有权限执行此操作~")
bot.Send(m.Chat, gettext.Gettext("noPermission"))
return
}
logs := GetRecentLogs(bLogBasePath, 5)
@ -290,7 +290,7 @@ func bLog(m *tb.Message) {
bot.Handle(&inlineBtn, bLogsInlineBtn)
inlineKeys = append(inlineKeys, []tb.InlineButton{inlineBtn})
}
_, err := bot.Send(m.Chat, "选择一个日志", &tb.ReplyMarkup{InlineKeyboard: inlineKeys})
_, err := bot.Send(m.Chat, gettext.Gettext("logs"), &tb.ReplyMarkup{InlineKeyboard: inlineKeys})
if err != nil {
logger.Println(err)
}

220
language.go Normal file
View File

@ -0,0 +1,220 @@
package main
const jsonData = `{
"zh_CN": {
"LC_MESSAGES": {
"resources.json": [{
"msgid" : "helpContent",
"msgstr" : ["命令:\n/my 查看已绑定账户信息\n/bind 绑定新账户\n/unbind 解绑账户\n/export 导出账户信息(JSON格式)\n/help 帮助\n/task 手动执行一次任务(管理员)\n/log 获取最近日志文件(管理员)\n源代码https://github.com/rainerosion/E5SubBotForSQLite\n原作者https://github.com/iyear/E5SubBot"]
},{
"msgid" : "welcome",
"msgstr" : ["欢迎使用E5SubBot!"]
},{
"msgid" : "chooseAnAccount",
"msgstr" : ["选择一个账户查看具体信息\n\n绑定数: "]
},{
"msgid" : "accountInformation",
"msgstr" : ["信息\n别名"]
},{
"msgid" : "updateTime",
"msgstr" : ["\n最近更新时间: "]
},{
"msgid" : "register",
"msgstr" : ["应用注册: [点击直达]"]
},{
"msgid" : "bind1Reply",
"msgstr" : ["请回复client_id+空格+client_secret"]
},{
"msgid" : "formatError",
"msgstr" : ["错误的格式"]
},{
"msgid" : "signIn",
"msgstr" : ["授权账户: [点击直达]"]
},{
"msgid" : "bind2Reply",
"msgstr" : ["请回复http://localhost/…… + 空格 + 别名(用于管理)"]
},{
"msgid" : "unBind",
"msgstr" : ["选择一个账户将其解绑\n\n当前绑定数: "]
},{
"msgid" : "unBindError",
"msgstr" : ["解绑失败!"]
},{
"msgid" : "unBindSuccess",
"msgstr" : ["解绑成功!"]
},{
"msgid" : "unbound",
"msgstr" : ["你还没有绑定过账户嗷~"]
},{
"msgid" : "json",
"msgstr" : ["获取JSON失败\n"]
},{
"msgid" : "temporary",
"msgstr" : ["写入临时文件失败~\n"]
},{
"msgid" : "getHelp",
"msgstr" : ["发送/help获取帮助嗷"]
},{
"msgid" : "replyBind",
"msgstr" : ["请通过回复方式绑定"]
},{
"msgid" : "maximum",
"msgstr" : ["已经达到最大可绑定数"]
},{
"msgid" : "binding",
"msgstr" : ["正在绑定中……"]
},{
"msgid" : "bindSuccess",
"msgstr" : ["绑定成功!"]
},{
"msgid" : "logs",
"msgstr" : ["选择一个日志"]
},{
"msgid" : "noPermission",
"msgstr" : ["您没有权限执行此操作~"]
},{
"msgid" : "bindFormatError",
"msgstr" : ["绑定格式错误"]
},{
"msgid" : "getToken",
"msgstr" : ["Token获取成功!"]
},{
"msgid" : "alreadyBind",
"msgstr" : ["该应用已经绑定过了,无需重复绑定!"]
},{
"msgid" : "taskError",
"msgstr" : ["您的账户: %s 在任务执行时出现了错误!\n错误:"]
},{
"msgid" : "clickToUnBind",
"msgstr" : ["点击解绑该账户"]
},{
"msgid" : "unBindByMaxLimit",
"msgstr" : ["您的账户因达到错误上限而被自动解绑\n后会有期!\n\n别名: "]
},{
"msgid" : "taskFeedback",
"msgstr" : ["任务反馈\n时间: "]
},{
"msgid" : "result",
"msgstr" : ["\n结果: "]
},{
"msgid" : "taskFeedbackAdmin",
"msgstr" : ["任务反馈(管理员)\n完成时间: "]
},{
"msgid" : "wrongAccount",
"msgstr" : ["\n错误账户:\n"]
},{
"msgid" : "clearingAccount",
"msgstr" : ["\n清退账户:\n"]
}
]
}
},
"en_US": {
"LC_MESSAGES": {
"resources.json": [{
"msgid" : "helpContent",
"msgstr" : ["/my View bound account information\n/bind Bind new account\n/unbind Unbind account\n/export Export account information (JSON format)\n/help help\n/task Manually execute a task (Bot Administrator)\n/log Get the most recent log file (Bot Administrator)\nSource Codehttps://github.com/rainerosion/E5SubBotForSQLite\nOriginal Authorhttps://github.com/iyear/E5SubBot"]
},{
"msgid" : "welcome",
"msgstr" : ["Welcome to E5SubBot!"]
},{
"msgid" : "chooseAnAccount",
"msgstr" : ["Select an account to view information.\n\nNumber of bindings: "]
},{
"msgid" : "accountInformation",
"msgstr" : ["Account information\nAlias: "]
},{
"msgid" : "updateTime",
"msgstr" : ["\nUpdate Time: "]
},{
"msgid" : "register",
"msgstr" : ["Application registration [Click here]"]
},{
"msgid" : "bind1Reply",
"msgstr" : ["Please reply client_id+Space+client_secret"]
},{
"msgid" : "formatError",
"msgstr" : ["Format error"]
},{
"msgid" : "signIn",
"msgstr" : ["Login account [Click here]"]
},{
"msgid" : "bind2Reply",
"msgstr" : ["Please reply http://localhost/…… + Space + Alias(for management)"]
},{
"msgid" : "unBind",
"msgstr" : ["Select the account to be unbound.\n\nNumber of bindings: "]
},{
"msgid" : "unBindError",
"msgstr" : ["Unbind failed!"]
},{
"msgid" : "unBindSuccess",
"msgstr" : ["Successfully unbound!"]
},{
"msgid" : "unbound",
"msgstr" : ["You haven't tied an account yet."]
},{
"msgid" : "json",
"msgstr" : ["Failed to get json\n"]
},{
"msgid" : "temporary",
"msgstr" : ["Write to temporary file failed.\n"]
},{
"msgid" : "getHelp",
"msgstr" : ["Send /help for help"]
},{
"msgid" : "replyBind",
"msgstr" : ["Please bind by reply."]
},{
"msgid" : "maximum",
"msgstr" : ["The maximum number of bindings has been reached."]
},{
"msgid" : "binding",
"msgstr" : ["Binding……"]
},{
"msgid" : "bindSuccess",
"msgstr" : ["Binding succeeded!"]
},{
"msgid" : "logs",
"msgstr" : ["Select a log."]
},{
"msgid" : "noPermission",
"msgstr" : ["You do not have permission."]
},{
"msgid" : "bindFormatError",
"msgstr" : ["Format error"]
},{
"msgid" : "getToken",
"msgstr" : ["Token obtained successfully!"]
},{
"msgid" : "alreadyBind",
"msgstr" : ["Account already exists!"]
},{
"msgid" : "taskError",
"msgstr" : ["The account %s an error.\nError details:"]
},{
"msgid" : "clickToUnBind",
"msgstr" : ["Click to unbundle this account"]
},{
"msgid" : "unBindByMaxLimit",
"msgstr" : ["Your account has been automatically unbundled due to an error limit being reached\nAccount alias: "]
},{
"msgid" : "taskFeedback",
"msgstr" : ["Task feedback\nTime: "]
},{
"msgid" : "result",
"msgstr" : ["\nResult: "]
},{
"msgid" : "taskFeedbackAdmin",
"msgstr" : ["Task feedback(administrator)\nExecution time: "]
},{
"msgid" : "wrongAccount",
"msgstr" : ["\nWrong account:\n"]
},{
"msgid" : "clearingAccount",
"msgstr" : ["\nClearing account:\n"]
}
]
}
}
}`