diff --git a/README.md b/README.md
index 4d1176f5ac..619054faba 100644
--- a/README.md
+++ b/README.md
@@ -651,6 +651,16 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 教你一篇小作文[作文]
+
+
+ 程序员做饭指南
+
+ `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/dish"`
+
+ - [x] 怎么做 | 烹饪[菜名]
+
+ - [x] 随机菜谱 | 随便做点菜
+
多功能抽签
diff --git a/main.go b/main.go
index 0ac64b99e8..2086330ea2 100644
--- a/main.go
+++ b/main.go
@@ -82,6 +82,7 @@ import (
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/dailynews" // 今日早报
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/danbooru" // DeepDanbooru二次元图标签识别
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/diana" // 嘉心糖发病
+ _ "github.com/FloatTech/ZeroBot-Plugin/plugin/dish" // 程序员做饭指南
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/drawlots" // 多功能抽签
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/dress" // 女装
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/drift_bottle" // 漂流瓶
diff --git a/plugin/dish/dish.go b/plugin/dish/dish.go
new file mode 100644
index 0000000000..72a7f75ab0
--- /dev/null
+++ b/plugin/dish/dish.go
@@ -0,0 +1,114 @@
+// Package dish 程序员做饭指南zbp版,数据来源Anduin2017/HowToCook
+package dish
+
+import (
+ "fmt"
+ "github.com/sirupsen/logrus"
+ "strings"
+ "time"
+
+ sql "github.com/FloatTech/sqlite"
+ ctrl "github.com/FloatTech/zbpctrl"
+ zero "github.com/wdvxdr1123/ZeroBot"
+
+ "github.com/FloatTech/zbputils/control"
+ "github.com/FloatTech/zbputils/ctxext"
+ "github.com/wdvxdr1123/ZeroBot/message"
+)
+
+type dish struct {
+ ID uint32 `db:"id"`
+ Name string `db:"name"`
+ Materials string `db:"materials"`
+ Steps string `db:"steps"`
+}
+
+var (
+ db = &sql.Sqlite{}
+ initialized = false
+)
+
+func init() {
+ en := control.Register("dish", &ctrl.Options[*zero.Ctx]{
+ DisableOnDefault: false,
+ Brief: "程序员做饭指南",
+ Help: "-怎么做[xxx]|烹饪[xxx]|随机菜谱|随便做点菜",
+ PublicDataFolder: "Dish",
+ })
+
+ db.DBPath = en.DataFolder() + "dishes.db"
+
+ if _, err := en.GetLazyData("dishes.db", true); err != nil {
+ logrus.Warnln("[dish]获取菜谱数据库文件失败")
+ } else if err = db.Open(time.Hour * 24); err != nil {
+ logrus.Warnln("[dish]连接菜谱数据库失败")
+ } else if err = db.Create("dishes", &dish{}); err != nil {
+ logrus.Warnln("[dish]同步菜谱数据表失败")
+ } else if count, err := db.Count("dishes"); err != nil {
+ logrus.Warnln("[dish]统计菜谱数据失败")
+ } else {
+ logrus.Infoln("[dish]加载", count, "条菜谱")
+ initialized = true
+ }
+
+ if !initialized {
+ logrus.Warnln("[dish]插件未能成功初始化")
+ }
+
+ en.OnPrefixGroup([]string{"怎么做", "烹饪"}).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
+ if !initialized {
+ ctx.SendChain(message.Text("客官,本店暂未开业"))
+ return
+ }
+
+ name := ctx.NickName()
+ dishName := ctx.State["args"].(string)
+
+ if dishName == "" {
+ return
+ }
+
+ if strings.Contains(dishName, "'") ||
+ strings.Contains(dishName, "\"") ||
+ strings.Contains(dishName, "\\") ||
+ strings.Contains(dishName, ";") {
+ return
+ }
+
+ var d dish
+ if err := db.Find("dishes", &d, fmt.Sprintf("WHERE name like %%%s%%", dishName)); err != nil {
+ return
+ }
+
+ ctx.SendChain(message.Text(fmt.Sprintf(
+ "已为客官%s找到%s的做法辣!\n"+
+ "原材料:%s\n"+
+ "步骤:\n"+
+ "%s",
+ name, dishName, d.Materials, d.Steps),
+ ))
+ })
+
+ en.OnPrefixGroup([]string{"随机菜谱", "随便做点菜"}).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
+ if !initialized {
+ ctx.SendChain(message.Text("客官,本店暂未开业"))
+ return
+ }
+
+ name := ctx.NickName()
+ var d dish
+ if err := db.Pick("dishes", &d); err != nil {
+ ctx.SendChain(message.Text("小店好像出错了,暂时端不出菜来惹"))
+ logrus.Warnln("[dish]随机菜谱请求出错:" + err.Error())
+ return
+ }
+
+ ctx.SendChain(message.Text(fmt.Sprintf(
+ "已为客官%s送上%s的做法:\n"+
+ "原材料:%s\n"+
+ "步骤:\n"+
+ "%s",
+ name, d.Name, d.Materials, d.Steps),
+ ))
+ })
+}