1
0
forked from x/icebergs

add wx.shy

This commit is contained in:
IT 老营长 @云轩领航-创始人 2023-11-10 02:12:48 +08:00
parent 798dfd62aa
commit ab8de9ba49
30 changed files with 481 additions and 224 deletions

View File

@ -55,9 +55,9 @@ func SessAuth(m *ice.Message, value ice.Any, arg ...string) *ice.Message {
value = kit.Dict(USERNICK, kit.Select("", val, 0), USERNAME, kit.Select("", val, 1), USERROLE, kit.Select("", val, 2)) value = kit.Dict(USERNICK, kit.Select("", val, 0), USERNAME, kit.Select("", val, 1), USERROLE, kit.Select("", val, 2))
} }
return m.Auth( return m.Auth(
USERNICK, m.Option(ice.MSG_USERNICK, kit.Value(value, USERNICK)), USERNICK, m.Option(ice.MSG_USERNICK, kit.Format(kit.Value(value, USERNICK))),
USERNAME, m.Option(ice.MSG_USERNAME, kit.Value(value, USERNAME)), USERNAME, m.Option(ice.MSG_USERNAME, kit.Format(kit.Value(value, USERNAME))),
USERROLE, m.Option(ice.MSG_USERROLE, kit.Value(value, USERROLE)), USERROLE, m.Option(ice.MSG_USERROLE, kit.Format(kit.Value(value, USERROLE))),
arg, logs.FileLineMeta(kit.Select(logs.FileLine(-1), m.Option("aaa.checker"))), arg, logs.FileLineMeta(kit.Select(logs.FileLine(-1), m.Option("aaa.checker"))),
) )
} }

View File

@ -56,6 +56,7 @@ func init() {
} }
func UserInfo(m *ice.Message, name ice.Any, key, meta string) (value string) { func UserInfo(m *ice.Message, name ice.Any, key, meta string) (value string) {
if m.Cmd(USER, kit.Select(m.Option(ice.MSG_USERNAME), name), func(val ice.Maps) { value = val[key] }).Length() == 0 && kit.Format(name) == m.Option(ice.MSG_USERNAME) { if m.Cmd(USER, kit.Select(m.Option(ice.MSG_USERNAME), name), func(val ice.Maps) { value = val[key] }).Length() == 0 && kit.Format(name) == m.Option(ice.MSG_USERNAME) {
return m.Option(meta) return m.Option(meta)
} }

View File

@ -1,9 +1,14 @@
package cli package cli
import ice "shylinux.com/x/icebergs" import (
ice "shylinux.com/x/icebergs"
kit "shylinux.com/x/toolkits"
)
const CLI = "cli" const CLI = "cli"
var Index = &ice.Context{Name: CLI, Help: "命令模块"} var Index = &ice.Context{Name: CLI, Help: "命令模块"}
func Prefix(arg ...string) string { return kit.Keys(CLI, arg) }
func init() { ice.Index.Register(Index, nil, RUNTIME, SYSTEM, DAEMON, FOREVER, MIRRORS, QRCODE) } func init() { ice.Index.Register(Index, nil, RUNTIME, SYSTEM, DAEMON, FOREVER, MIRRORS, QRCODE) }

View File

@ -50,7 +50,7 @@ func init() {
QRCODE: {Name: "qrcode text fg@key bg@key size auto", Help: "二维码", Actions: ice.Actions{ QRCODE: {Name: "qrcode text fg@key bg@key size auto", Help: "二维码", Actions: ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
ice.AddRender(ice.RENDER_QRCODE, func(m *ice.Message, args ...ice.Any) string { ice.AddRender(ice.RENDER_QRCODE, func(m *ice.Message, args ...ice.Any) string {
return m.Cmd(QRCODE, kit.Simple(args...)).Result() return m.Cmd(Prefix(QRCODE), kit.Simple(args...)).Result()
}) })
}}, }},
mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) {

View File

@ -44,13 +44,13 @@ var list map[string]int = map[string]int{}
func Watch(m *ice.Message, key string, arg ...string) *ice.Message { func Watch(m *ice.Message, key string, arg ...string) *ice.Message {
kit.If(len(arg) == 0, func() { arg = append(arg, m.PrefixKey()) }) kit.If(len(arg) == 0, func() { arg = append(arg, m.PrefixKey()) })
return m.Cmd(EVENT, LISTEN, EVENT, key, ice.CMD, kit.Join(arg, ice.SP)) return m.Cmd(Prefix(EVENT), LISTEN, EVENT, key, ice.CMD, kit.Join(arg, ice.SP))
} }
func Event(m *ice.Message, key string, arg ...ice.Any) *ice.Message { func Event(m *ice.Message, key string, arg ...ice.Any) *ice.Message {
if key = kit.Select(kit.Keys(m.CommandKey(), m.ActionKey()), key); list[key] == 0 { if key = kit.Select(kit.Keys(m.CommandKey(), m.ActionKey()), key); list[key] == 0 {
return m return m
} }
return m.Cmdy(EVENT, HAPPEN, EVENT, key, arg, logs.FileLineMeta(-1)) return m.Cmdy(Prefix(EVENT), HAPPEN, EVENT, key, arg, logs.FileLineMeta(-1))
} }
func EventDeferEvent(m *ice.Message, key string, arg ...ice.Any) func(string, ...ice.Any) { func EventDeferEvent(m *ice.Message, key string, arg ...ice.Any) func(string, ...ice.Any) {
Event(m, key, arg...) Event(m, key, arg...)

View File

@ -49,4 +49,6 @@ const GDB = "gdb"
var Index = &ice.Context{Name: GDB, Help: "事件模块"} var Index = &ice.Context{Name: GDB, Help: "事件模块"}
func Prefix(arg ...string) string { return kit.Keys(GDB, arg) }
func init() { ice.Index.Register(Index, &Frame{}, SIGNAL, EVENT, TIMER, ROUTINE) } func init() { ice.Index.Register(Index, &Frame{}, SIGNAL, EVENT, TIMER, ROUTINE) }

View File

@ -30,6 +30,12 @@ func RLock(m configMessage, arg ...string) func() { return getLock(m, arg...).RL
func Config(m configMessage, key string, arg ...Any) string { func Config(m configMessage, key string, arg ...Any) string {
return kit.Format(Configv(m, key, arg...)) return kit.Format(Configv(m, key, arg...))
} }
func ConfigSimple(m configMessage, key ...string) (res []string) {
for _, key := range key {
res = append(res, key, kit.Format(Configv(m, key)))
}
return
}
func Configv(m configMessage, key string, arg ...Any) Any { func Configv(m configMessage, key string, arg ...Any) Any {
kit.If(len(arg) > 0, func() { Confv(m, m.PrefixKey(), kit.Keym(key), arg[0]) }) kit.If(len(arg) > 0, func() { Confv(m, m.PrefixKey(), kit.Keym(key), arg[0]) })
return Confv(m, m.PrefixKey(), kit.Keym(key)) return Confv(m, m.PrefixKey(), kit.Keym(key))

View File

@ -92,6 +92,7 @@ const (
STORE = kit.MDB_STORE STORE = kit.MDB_STORE
FSIZE = kit.MDB_FSIZE FSIZE = kit.MDB_FSIZE
ICONS = "icons"
TOOLS = "tools" TOOLS = "tools"
SOURCE = "_source" SOURCE = "_source"
TARGET = "_target" TARGET = "_target"
@ -101,6 +102,7 @@ const (
INPUTS = "inputs" INPUTS = "inputs"
CREATE = "create" CREATE = "create"
REMOVE = "remove" REMOVE = "remove"
UPDATE = "update"
INSERT = "insert" INSERT = "insert"
DELETE = "delete" DELETE = "delete"
MODIFY = "modify" MODIFY = "modify"

View File

@ -185,3 +185,9 @@ func ProxyUpload(m *ice.Message, pod string, p string) string {
m.Cmd(SPACE, pod, SPIDE, PROXY, URL, url, nfs.SIZE, size, CACHE, cache.Format(ice.MOD_TIME), UPLOAD, mdb.AT+p) m.Cmd(SPACE, pod, SPIDE, PROXY, URL, url, nfs.SIZE, size, CACHE, cache.Format(ice.MOD_TIME), UPLOAD, mdb.AT+p)
return kit.Select(p, pp, file.ExistsFile(pp)) return kit.Select(p, pp, file.ExistsFile(pp))
} }
func ShareLocal(m *ice.Message, p string) string {
if kit.HasPrefix(p, nfs.PS, HTTP) {
return p
}
return MergeLink(m, "/share/local/"+p)
}

View File

@ -23,7 +23,7 @@ const FAVOR = "favor"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
FAVOR: {Help: "收藏夹", Icon: "favor.png", Actions: ice.MergeActions(ice.Actions{ FAVOR: {Name: "favor hash auto", Help: "收藏夹", Icon: "favor.png", Actions: ice.MergeActions(ice.Actions{
mdb.SEARCH: {Hand: func(m *ice.Message, arg ...string) { mdb.SEARCH: {Hand: func(m *ice.Message, arg ...string) {
if mdb.IsSearchPreview(m, arg) { if mdb.IsSearchPreview(m, arg) {
m.Cmds("", func(value ice.Maps) { m.Cmds("", func(value ice.Maps) {
@ -58,7 +58,7 @@ func init() {
"scanQRCode": {Name: "favor create", Help: "扫码"}, "scanQRCode": {Name: "favor create", Help: "扫码"},
"record1": {Name: "favor upload", Help: "截图"}, "record1": {Name: "favor upload", Help: "截图"},
"record2": {Name: "favor upload", Help: "录屏"}, "record2": {Name: "favor upload", Help: "录屏"},
mdb.CREATE: {Name: "create type name text", Hand: func(m *ice.Message, arg ...string) { mdb.CREATE: {Name: "create type name text*", Hand: func(m *ice.Message, arg ...string) {
if strings.HasPrefix(m.Option(mdb.TEXT), ice.HTTP) { if strings.HasPrefix(m.Option(mdb.TEXT), ice.HTTP) {
m.OptionDefault(mdb.TYPE, mdb.LINK, mdb.NAME, kit.ParseURL(m.Option(mdb.TEXT)).Host) m.OptionDefault(mdb.TYPE, mdb.LINK, mdb.NAME, kit.ParseURL(m.Option(mdb.TEXT)).Host)
} }
@ -81,7 +81,7 @@ func init() {
} }
}}, }},
cli.OPENS: {Hand: func(m *ice.Message, arg ...string) { cli.Opens(m, m.Option(mdb.TEXT)) }}, cli.OPENS: {Hand: func(m *ice.Message, arg ...string) { cli.Opens(m, m.Option(mdb.TEXT)) }},
}, FavorAction(), mdb.ExportHashAction()), Hand: func(m *ice.Message, arg ...string) { }, FavorAction(), mdb.ExportHashAction(mdb.SHORT, mdb.TEXT, mdb.FIELD, "time,hash,type,name,text")), Hand: func(m *ice.Message, arg ...string) {
if len(arg) > 0 && arg[0] == ctx.ACTION { if len(arg) > 0 && arg[0] == ctx.ACTION {
if m.Option(ice.MSG_INDEX) == m.PrefixKey() { if m.Option(ice.MSG_INDEX) == m.PrefixKey() {
m.Option(mdb.TYPE, mdb.HashSelects(m.Spawn(), m.Option(mdb.HASH)).Append(mdb.TYPE)) m.Option(mdb.TYPE, mdb.HashSelects(m.Spawn(), m.Option(mdb.HASH)).Append(mdb.TYPE))
@ -98,6 +98,7 @@ func init() {
} else { } else {
m.Action(mdb.CREATE, web.UPLOAD, "getClipboardData", "record1", "record2") m.Action(mdb.CREATE, web.UPLOAD, "getClipboardData", "record1", "record2")
} }
m.SortStrR(mdb.TIME)
} else { } else {
if web.PodCmd(m, web.SPACE, arg...) { if web.PodCmd(m, web.SPACE, arg...) {
return return

View File

@ -99,7 +99,7 @@ func init() {
m.Option("language.list", m.Cmd(nfs.DIR, nfs.TemplatePath(m, aaa.LANGUAGE)+nfs.PS, nfs.FILE).Appendv(nfs.FILE)) m.Option("language.list", m.Cmd(nfs.DIR, nfs.TemplatePath(m, aaa.LANGUAGE)+nfs.PS, nfs.FILE).Appendv(nfs.FILE))
m.Option("theme.list", m.Cmd(nfs.DIR, nfs.TemplatePath(m, aaa.THEME)+nfs.PS, nfs.FILE).Appendv(nfs.FILE)) m.Option("theme.list", m.Cmd(nfs.DIR, nfs.TemplatePath(m, aaa.THEME)+nfs.PS, nfs.FILE).Appendv(nfs.FILE))
m.Option(nfs.REPOS, m.Cmdv(web.SPIDE, nfs.REPOS, web.CLIENT_URL)) m.Option(nfs.REPOS, m.Cmdv(web.SPIDE, nfs.REPOS, web.CLIENT_URL))
m.Option(ICONS, mdb.Conf(m, ICONS, kit.Keym(nfs.PATH))) m.Option("icons", mdb.Conf(m, ICON, kit.Keym(nfs.PATH)))
m.Option(MENUS, mdb.Config(m, MENUS)) m.Option(MENUS, mdb.Config(m, MENUS))
m.Echo(mdb.Config(m, TITLE)) m.Echo(mdb.Config(m, TITLE))
if mdb.HashSelect(m); m.Length() == 0 { if mdb.HashSelect(m); m.Length() == 0 {

View File

@ -11,11 +11,11 @@ import (
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
const ICONS = "icons" const ICON = "icon"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
ICONS: {Help: "图标", Actions: ctx.ConfAction(nfs.PATH, "bootstrap-icons/font/bootstrap-icons.css"), Hand: func(m *ice.Message, arg ...string) { ICON: {Help: "图标", Actions: ctx.ConfAction(nfs.PATH, "bootstrap-icons/font/bootstrap-icons.css"), Hand: func(m *ice.Message, arg ...string) {
m.Cmd(lex.SPLIT, ice.USR_MODULES+mdb.Config(m, nfs.PATH), kit.Dict(lex.SPLIT_SPACE, " {:;}"), func(text string, ls []string) { m.Cmd(lex.SPLIT, ice.USR_MODULES+mdb.Config(m, nfs.PATH), kit.Dict(lex.SPLIT_SPACE, " {:;}"), func(text string, ls []string) {
if len(ls) > 2 && ls[2] == nfs.CONTENT { if len(ls) > 2 && ls[2] == nfs.CONTENT {
name := "bi " + strings.TrimPrefix(ls[0], nfs.PT) name := "bi " + strings.TrimPrefix(ls[0], nfs.PT)

View File

@ -1,4 +1,4 @@
package chat package location
import ( import (
"path" "path"

View File

@ -1,4 +1,4 @@
package chat package location
import ( import (
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"

View File

@ -1,4 +1,4 @@
package chat package location
import ( import (
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
@ -17,6 +17,7 @@ const (
CITY = "city" CITY = "city"
DISTRICT = "district" DISTRICT = "district"
STREET = "street" STREET = "street"
SCALE = "scale"
) )
const LOCATION = "location" const LOCATION = "location"

View File

@ -1,4 +1,4 @@
package chat package location
import ( import (
"net/http" "net/http"

View File

@ -2,6 +2,7 @@ package mall
import ( import (
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/ctx" "shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
@ -21,7 +22,7 @@ func init() {
mdb.CREATE: {Name: "create zone* name* text price* count*=1 units*=件,个,份,斤 image*=4@img"}, mdb.CREATE: {Name: "create zone* name* text price* count*=1 units*=件,个,份,斤 image*=4@img"},
mdb.MODIFY: {Name: "modify zone* name* text price* count*=1 units*=件,个,份,斤 image*=4@img"}, mdb.MODIFY: {Name: "modify zone* name* text price* count*=1 units*=件,个,份,斤 image*=4@img"},
ORDER: {Name: "order count*=1", Help: "选购", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(CART, mdb.INSERT, arg) }}, ORDER: {Name: "order count*=1", Help: "选购", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(CART, mdb.INSERT, arg) }},
}, web.ExportCacheAction(nfs.IMAGE), mdb.ExportHashAction(ctx.TOOLS, kit.Fields(Prefix(CART), Prefix(ORDER)), mdb.FIELD, "time,hash,zone,name,text,price,count,units,image")), Hand: func(m *ice.Message, arg ...string) { }, aaa.RoleAction(), web.ExportCacheAction(nfs.IMAGE), mdb.ExportHashAction(ctx.TOOLS, kit.Fields(Prefix(CART), Prefix(ORDER)), mdb.FIELD, "time,hash,zone,name,text,price,count,units,image")), Hand: func(m *ice.Message, arg ...string) {
kit.If(len(arg) == 0 && m.IsMobileUA(), func() { m.OptionDefault(ice.MSG_FIELDS, "zone,name,price,count,units,text,hash,time,image") }) kit.If(len(arg) == 0 && m.IsMobileUA(), func() { m.OptionDefault(ice.MSG_FIELDS, "zone,name,price,count,units,text,hash,time,image") })
mdb.HashSelect(m, arg...).PushAction(ORDER).Action("filter:text") mdb.HashSelect(m, arg...).PushAction(ORDER).Action("filter:text")
web.PushPodCmd(m, "", arg...).Sort("zone,name") web.PushPodCmd(m, "", arg...).Sort("zone,name")

View File

@ -4,96 +4,84 @@ import (
"crypto/sha1" "crypto/sha1"
"net/http" "net/http"
"strings" "strings"
"time"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/ctx" "shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/gdb"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/tcp" "shylinux.com/x/icebergs/base/tcp"
"shylinux.com/x/icebergs/base/web" "shylinux.com/x/icebergs/base/web"
"shylinux.com/x/icebergs/core/chat" "shylinux.com/x/icebergs/base/web/html"
"shylinux.com/x/icebergs/core/chat/oauth"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
func _wx_sign(m *ice.Message, nonce, stamp string) string {
return kit.Format(sha1.Sum([]byte(kit.Join(kit.Sort(kit.Simple(
kit.Format("jsapi_ticket=%s", m.Cmdx(ACCESS, TICKET)),
kit.Format("url=%s", m.Option(ice.MSG_USERWEB)),
kit.Format("timestamp=%s", stamp),
kit.Format("noncestr=%s", nonce),
)), "&"))))
}
func _wx_config(m *ice.Message, nonce string) {
m.Option("signature", _wx_sign(m, m.Option("noncestr", nonce), m.Option("timestamp", kit.Format(time.Now().Unix()))))
ctx.OptionFromConfig(m, APPID, nfs.SCRIPT)
}
func _wx_check(m *ice.Message) {
check := kit.Sort([]string{mdb.Config(m, TOKEN), m.Option("timestamp"), m.Option("nonce")})
if sig := kit.Format(sha1.Sum([]byte(strings.Join(check, "")))); !m.Warn(sig != m.Option("signature"), ice.ErrNotRight, check) {
kit.If(m.Option("echostr") != "", func() { m.RenderResult(m.Option("echostr")) }, func() { m.Echo(ice.TRUE) })
}
}
const ( const (
APPID = "appid" APPID = "appid"
APPMM = "appmm" SECRET = "secret"
TOKEN = "token" TOKEN = "token"
TOKENS = "tokens" TOKENS = "tokens"
EXPIRES = "expires" EXPIRES = "expires"
TICKET = "ticket" TICKET = "ticket"
EXPIRE = "expire" EXPIRE = "expire"
CONFIG = "config"
CHECK = "check"
) )
const ( const (
ERRCODE = "errcode" CGI_BIN = "https://api.weixin.qq.com/cgi-bin/"
ERRMSG = "errmsg" QRCODE_CREATE = "qrcode/create"
MENU_CREATE = "menu/create"
USER_INFO = "user/info"
USER_GET = "user/get"
) )
const ACCESS = "access" const ACCESS = "access"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
ACCESS: {Name: "access appid auto ticket tokens login", Help: "认证", Actions: ice.MergeActions(ice.Actions{ ACCESS: {Help: "认证", Meta: Meta(), Actions: ice.MergeActions(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { m.Cmd(web.SPIDE, mdb.CREATE, WX, mdb.Config(m, tcp.SERVER)) }},
m.Cmd(web.SPIDE, mdb.CREATE, WX, mdb.Config(m, tcp.SERVER)) mdb.CREATE: {Name: "login usernick access* appid* secret* token* icons", Help: "登录", Hand: func(m *ice.Message, arg ...string) {
gdb.Watch(m, chat.HEADER_AGENT, m.PrefixKey()) mdb.HashCreate(m, m.OptionSimple(aaa.USERNICK, ACCESS, APPID, SECRET, TOKEN, mdb.ICONS))
ctx.ConfigFromOption(m, ACCESS, APPID, TOKEN)
}}, }},
chat.HEADER_AGENT: {Hand: func(m *ice.Message, arg ...string) { aaa.CHECK: {Hand: func(m *ice.Message, arg ...string) {
if strings.Index(m.Option(ice.MSG_USERUA), "MicroMessenger") > -1 { check := kit.Sort([]string{mdb.Config(m, TOKEN), m.Option(TIMESTAMP), m.Option(NONCE)})
_wx_config(m, mdb.Config(m, APPID)) if sig := kit.Format(sha1.Sum([]byte(strings.Join(check, "")))); !m.Warn(sig != m.Option(SIGNATURE), ice.ErrNotRight, check) {
m.Echo(ice.TRUE)
} }
}}, }},
LOGIN: {Name: "login appid appmm token", Help: "登录", Hand: func(m *ice.Message, arg ...string) { AGENT: {Hand: func(m *ice.Message, arg ...string) { ctx.OptionFromConfig(m, ACCESS, APPID) }},
ctx.ConfigFromOption(m, APPID, APPMM, TOKEN) TOKENS: {Hand: func(m *ice.Message, arg ...string) {
msg := mdb.HashSelect(m.Spawn(), m.Option(ACCESS))
if msg.Append(TOKENS) == "" || m.Time() > msg.Append(EXPIRES) {
res := m.Cmd(web.SPIDE, WX, http.MethodGet, "token?grant_type=client_credential", msg.AppendSimple(APPID, SECRET))
mdb.HashModify(m, m.OptionSimple(ACCESS), EXPIRES, m.Time(kit.Format("%vs", res.Append(oauth.EXPIRES_IN))), TOKENS, res.Append(oauth.ACCESS_TOKEN))
msg = mdb.HashSelect(m.Spawn(), m.Option(ACCESS))
}
m.Echo(msg.Append(TOKENS)).Status(msg.AppendSimple(EXPIRES))
}}, }},
TOKENS: {Help: "令牌", Hand: func(m *ice.Message, arg ...string) { TICKET: {Hand: func(m *ice.Message, arg ...string) {
if now := time.Now().Unix(); mdb.Config(m, TOKENS) == "" || now > kit.Int64(mdb.Config(m, EXPIRES)) { msg := mdb.HashSelect(m.Spawn(), m.Option(ACCESS))
msg := m.Cmd(web.SPIDE, WX, http.MethodGet, "/cgi-bin/token?grant_type=client_credential", APPID, mdb.Config(m, APPID), "secret", mdb.Config(m, APPMM)) if msg.Append(TICKET) == "" || m.Time() > msg.Append(EXPIRE) {
if m.Warn(msg.Append(ERRCODE) != "", msg.Append(ERRCODE), msg.Append(ERRMSG)) { res := m.Cmd(web.SPIDE, WX, http.MethodGet, "ticket/getticket?type=jsapi", arg, oauth.ACCESS_TOKEN, m.Cmdx(ACCESS, TOKENS))
return mdb.HashModify(m, m.OptionSimple(ACCESS), EXPIRE, m.Time(kit.Format("%vs", res.Append(oauth.EXPIRES_IN))), TICKET, res.Append(TICKET))
msg = mdb.HashSelect(m.Spawn(), m.Option(ACCESS))
} }
mdb.Config(m, EXPIRES, now+kit.Int64(msg.Append("expires_in"))) m.Echo(msg.Append(TICKET)).Status(msg.AppendSimple(EXPIRE))
mdb.Config(m, TOKENS, msg.Append("access_token"))
}
m.Echo(mdb.Config(m, TOKENS)).Status(EXPIRES, time.Unix(kit.Int64(mdb.Config(m, EXPIRES)), 0).Format(ice.MOD_TIME))
}}, }},
TICKET: {Help: "票据", Hand: func(m *ice.Message, arg ...string) { }, mdb.ImportantHashAction(mdb.SHORT, ACCESS, mdb.FIELD, "time,access,usernick,appid,icons", tcp.SERVER, CGI_BIN)), Hand: func(m *ice.Message, arg ...string) {
if now := time.Now().Unix(); mdb.Config(m, TICKET) == "" || now > kit.Int64(mdb.Config(m, EXPIRE)) { mdb.HashSelect(m, arg...).StatusTimeCount(mdb.ConfigSimple(m, ACCESS, APPID), web.LINK, web.MergeURL2(m, "/chat/wx/login/"))
msg := m.Cmd(web.SPIDE, WX, http.MethodGet, "/cgi-bin/ticket/getticket?type=jsapi", "access_token", m.Cmdx("", TOKENS))
if m.Warn(msg.Append(ERRCODE) != "0", msg.Append(ERRCODE), msg.Append(ERRMSG)) {
return
}
mdb.Config(m, EXPIRE, now+kit.Int64(msg.Append("expires_in")))
mdb.Config(m, TICKET, msg.Append(TICKET))
}
m.Echo(mdb.Config(m, TICKET)).Status(EXPIRE, time.Unix(kit.Int64(mdb.Config(m, EXPIRE)), 0).Format(ice.MOD_TIME))
}},
CONFIG: {Hand: func(m *ice.Message, arg ...string) { _wx_config(m, mdb.Config(m, APPID)) }},
CHECK: {Hand: func(m *ice.Message, arg ...string) { _wx_check(m) }},
}, mdb.HashAction(tcp.SERVER, "https://api.weixin.qq.com", nfs.SCRIPT, "/plugin/local/chat/wx.js")), Hand: func(m *ice.Message, arg ...string) {
m.Echo(mdb.Config(m, APPID))
}}, }},
}) })
} }
func SpideGet(m *ice.Message, api string, arg ...ice.Any) ice.Any {
return kit.UnMarshal(m.Cmdx(web.SPIDE, WX, web.SPIDE_RAW, http.MethodGet, kit.MergeURL(api, oauth.ACCESS_TOKEN, m.Cmdx(ACCESS, TOKENS)), arg))
}
func SpidePost(m *ice.Message, api string, arg ...ice.Any) ice.Any {
return kit.UnMarshal(m.Cmdx(web.SPIDE, WX, web.SPIDE_RAW, http.MethodPost, kit.MergeURL(api, oauth.ACCESS_TOKEN, m.Cmdx(ACCESS, TOKENS)), arg))
}
func Meta() ice.Map {
return kit.Dict(ice.CTX_TRANS, kit.Dict(html.INPUT, kit.Dict(
ACCESS, "账号", APPID, "应用", SECRET, "密码",
EXPIRE_SECONDS, "有效期",
SCENE, "场景", RIVER, "一级", STORM, "二级",
)))
}

46
misc/wx/agent.go Normal file
View File

@ -0,0 +1,46 @@
package wx
import (
"crypto/sha1"
"strings"
"time"
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/gdb"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/web"
"shylinux.com/x/icebergs/core/chat"
"shylinux.com/x/icebergs/core/chat/location"
kit "shylinux.com/x/toolkits"
)
func _wx_sign(m *ice.Message, nonce, stamp string) string {
return kit.Format(sha1.Sum([]byte(kit.Join(kit.Sort(kit.Simple(
kit.Format("jsapi_ticket=%s", m.Cmdx(ACCESS, TICKET)),
kit.Format("url=%s", m.R.Header.Get(web.Referer)),
kit.Format("timestamp=%s", stamp),
kit.Format("noncestr=%s", nonce),
)), "&"))))
}
const (
SIGNATURE = "signature"
TIMESTAMP = "timestamp"
NONCESTR = "noncestr"
NONCE = "nonce"
)
const AGENT = "agent"
func init() {
Index.MergeCommands(ice.Commands{
AGENT: {Name: "agent auto", Actions: ice.MergeActions(ice.Actions{
chat.HEADER_AGENT: {Hand: func(m *ice.Message, arg ...string) {
kit.If(strings.Index(m.Option(ice.MSG_USERUA), "MicroMessenger") > -1, func() { m.Option(mdb.PLUGIN, m.PrefixKey()) })
}},
"scanQRCode1": {Hand: func(m *ice.Message, arg ...string) { m.Cmdy(chat.FAVOR, mdb.CREATE, arg) }},
"getLocation": {Hand: func(m *ice.Message, arg ...string) { m.Cmdy(location.LOCATION, mdb.CREATE, arg) }},
}, gdb.EventsAction(chat.HEADER_AGENT)), Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(ACCESS, AGENT).Options(SIGNATURE, _wx_sign(m, m.Option(NONCESTR, "some"), m.Option(TIMESTAMP, kit.Format(time.Now().Unix())))).Display("")
}},
})
}

111
misc/wx/agent.js Normal file
View File

@ -0,0 +1,111 @@
Volcanos(chat.ONIMPORT, {
_init: function(can, msg) { msg.Option(ice.MSG_ACTION, ""), can.require(["https://res.wx.qq.com/open/js/jweixin-1.6.0.js"], function(can) {
wx.config({debug: msg.Option("debug") == ice.TRUE, signature: msg.Option("signature"), timestamp: msg.Option("timestamp"), nonceStr: msg.Option("noncestr"), appId: msg.Option("appid"),
jsApiList: can.core.Item({
scanQRCode: function(can, cb) { wx.scanQRCode({needResult: cb? 1: 0, scanType: ["qrCode","barCode"], success: function (res) {
can.base.isFunc(cb) && cb(can.base.ParseJSON(res.resultStr))
} }) },
getLocation: function(can, cb) { wx.getLocation({type: "gcj02", success: function (res) {
can.base.isFunc(cb) && cb({type: "gcj02", name: "当前位置", text: "当前位置", latitude: parseInt(res.latitude*100000), longitude: parseInt(res.longitude*100000) })
} }) },
openLocation: function(can, msg) { wx.openLocation({
name: msg.Option(mdb.NAME), address: msg.Option(mdb.TEXT), infoUrl: msg.Option(mdb.LINK),
longitude: parseFloat(msg.Option("longitude")), latitude: parseFloat(msg.Option("latitude")), scale: msg.Option("scale")||14,
}) },
chooseImage: function(can, cb, count) { wx.chooseImage({count: count||9, sizeType: ['original', 'compressed'], sourceType: ['album', 'camera'], success: function (res) {
can.base.isFunc(cb) && cb(res.localIds)
} }) },
}, function(key, value) { return can.user.agent[key] = value, key }).concat([
// "uploadImage", "previewImage",
// "updateAppMessageShareData", "updateTimelineShareData",
]),
})
}) },
})
Volcanos(chat.ONACTION, {list: [
"scanQRCode", "scanQRCode1", "getLocation", "openLocation",
"uploadImage", "chooseImage", "previewImage",
"updateAppMessageShareData", "updateTimelineShareData",
"openAddress",
],
scanQRCode: function(event, can, button) {
wx.scanQRCode({needResult: 0, scanType: ["qrCode","barCode"]})
},
scanQRCode1: function(event, can, button) {
wx.scanQRCode({needResult: 1, scanType: ["qrCode","barCode"], success: function (res) {
can.run(event, [ctx.ACTION, button, mdb.TEXT, res.resultStr], function() {})
can._output.innerHTML = res.resultStr
} })
},
getLocation: function(event, can, button) {
wx.getLocation({type: "gcj02", success: function (res) {
can.run(event, [ctx.ACTION, button, mdb.NAME, "current", "longitude", res.longitude.toFixed(6), "latitude", res.latitude.toFixed(6)], function() {})
can._output.innerHTML = JSON.stringify(res)
} })
},
openLocation: function(event, can, button) {
wx.getLocation({type: "gcj02", success: function (res) { wx.openLocation(res) }})
},
uploadImage: function(event, can, button) {
wx.chooseImage({success: function (res) {
can.core.List(res.localIds, function(item) {
wx.uploadImage({
localId: item, isShowProgressTips: 1,
success: function (res) {
var serverId = res.serverId;
can._output.innerHTML = serverId
}
})
})
}})
},
chooseImage: function(event, can, button) {
wx.chooseImage({
// count: 9, sourceType: ['album', 'camera'], sizeType: ['original', 'compressed'],
success: function (res) {
can.page.Append(can, can._output, can.core.List(res.localIds, function(item) {
return {img: item, style: {"max-width": can.ConfWidth()}}
}))
}
})
},
previewImage: function(event, can, button) {
wx.previewImage({
urls: [
'https://2021.shylinux.com/share/local/usr/icons/timg.png',
"https://2021.shylinux.com/share/local/usr/icons/mall.png",
],
})
},
updateAppMessageShareData: function(event, can, button) {
wx.updateAppMessageShareData({
title: document.title, desc: "工具系统", link: location.href,
imgUrl: 'https://2021.shylinux.com/share/local/usr/icons/timg.png',
success: function (res) { can._output.innerHTML = JSON.stringify(res) },
})
},
updateTimelineShareData: function(event, can, button) {
wx.updateTimelineShareData({
title: document.title, desc: "工具系统", link: location.href,
imgUrl: 'https://2021.shylinux.com/share/local/usr/icons/timg.png',
success: function (res) { can._output.innerHTML = JSON.stringify(res) },
})
},
openAddress: function(event, can, button) {
wx.openAddress({
success: function (res) {
can._output.innerHTML = JSON.stringify(res)
var userName = res.userName; // 收货人姓名
var postalCode = res.postalCode; // 邮编
var provinceName = res.provinceName; // 国标收货地址第一级地址(省)
var cityName = res.cityName; // 国标收货地址第二级地址(市)
var countryName = res.countryName; // 国标收货地址第三级地址(国家)
var detailInfo = res.detailInfo; // 详细收货地址信息
var nationalCode = res.nationalCode; // 收货地址国家码
var telNumber = res.telNumber; // 收货人手机号码
}
})
},
})

View File

@ -1,16 +0,0 @@
package wx
import (
ice "shylinux.com/x/icebergs"
)
const EVENT = "event"
func init() {
Index.MergeCommands(ice.Commands{
EVENT: {Name: "event", Help: "事件", Actions: ice.Actions{
"subscribe": {Help: "订阅", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(MENU, "home") }},
"unsubscribe": {Help: "取关", Hand: func(m *ice.Message, arg ...string) {}},
}},
})
}

48
misc/wx/events.go Normal file
View File

@ -0,0 +1,48 @@
package wx
import (
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/web"
kit "shylinux.com/x/toolkits"
)
const EVENTS = "events"
func init() {
const (
SUBSCRIBE = "subscribe"
UNSUBSCRIBE = "unsubscribe"
SCAN = "scan"
SCANCODE_WAITMSG = "scancode_waitmsg"
CLICK = "click"
)
Index.MergeCommands(ice.Commands{
EVENTS: {Help: "事件", Actions: ice.Actions{
SUBSCRIBE: {Help: "订阅", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(TEXT, web.LINK, kit.MergeURL2(m.Option(ice.MSG_USERWEB), nfs.PS))
}},
UNSUBSCRIBE: {Help: "取关", Hand: func(m *ice.Message, arg ...string) {}},
SCAN: {Help: "扫码", Hand: func(m *ice.Message, arg ...string) {
msg := m.Cmd(QRCODE, m.Option(ACCESS), arg[0])
m.Options(ice.MSG_USERPOD, msg.Append(web.SPACE))
link := m.Cmd(web.SHARE, mdb.CREATE, mdb.TYPE, web.FIELD, mdb.NAME, msg.Append(ctx.INDEX), mdb.TEXT, msg.Append(ctx.ARGS)).Option(web.LINK)
m.Cmdy(TEXT, web.LINK, link, msg.Append(mdb.NAME), msg.Append(mdb.TEXT), msg.Append(mdb.ICONS))
}},
SCANCODE_WAITMSG: {Help: "扫码", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(TEXT, web.LINK, m.Option("ScanResult"))
}},
CLICK: {Help: "菜单", Hand: func(m *ice.Message, arg ...string) {
msg := m.Cmd(MENU, m.Option(ACCESS), arg[0])
m.Options(mdb.ICONS, msg.Append(mdb.ICONS), mdb.NAME, msg.Append(mdb.NAME), mdb.TEXT, kit.Select(msg.Append(ctx.INDEX), msg.Append(mdb.TEXT)))
if msg.Append(ctx.INDEX) == "" {
m.Cmdy(TEXT, web.LINK, kit.MergeURL2(m.Option(ice.MSG_USERWEB), nfs.PS))
} else {
m.Cmdy(TEXT, web.LINK, m.MergePodCmd("", msg.Append(ctx.INDEX), kit.Split(msg.Append(ctx.ARGS))))
}
}},
}},
})
}

View File

@ -1,22 +0,0 @@
package wx
import (
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/mdb"
kit "shylinux.com/x/toolkits"
)
const FAVOR = "favor"
func init() {
Index.MergeCommands(ice.Commands{
FAVOR: {Name: "favor text:text auto create", Help: "收藏", Actions: mdb.HashAction(
mdb.SHORT, mdb.TEXT, mdb.FIELD, "time,type,name,text", mdb.LINK, "https://open.weixin.qq.com/qr/code",
), Hand: func(m *ice.Message, arg ...string) {
mdb.HashSelect(m, arg...).Table(func(value ice.Maps) {
m.PushQRCode(mdb.SCAN, kit.MergeURL(mdb.Config(m, mdb.LINK), aaa.USERNAME, value[mdb.TEXT]))
})
}},
})
}

View File

@ -4,13 +4,16 @@ import (
"bytes" "bytes"
"encoding/xml" "encoding/xml"
"io/ioutil" "io/ioutil"
"strings"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/gdb"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/web" "shylinux.com/x/icebergs/base/web"
"shylinux.com/x/icebergs/core/chat" "shylinux.com/x/icebergs/core/chat"
"shylinux.com/x/icebergs/core/wiki" "shylinux.com/x/icebergs/core/chat/location"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
@ -22,70 +25,80 @@ func _wx_parse(m *ice.Message) {
MsgType string MsgType string
MsgId int64 MsgId int64
Event string Event string
EventKey string
Content string Content string
Title string
Description string
Url string
PicUrl string
Location_X float64 Location_X float64
Location_Y float64 Location_Y float64
Scale string Scale string
Label string Label string
Title string
Description string
MediaId int64
PicUrl string
Url string
ScanCodeInfo struct {
ScanType string
ScanResult string
}
}{} }{}
defer m.R.Body.Close() defer m.R.Body.Close()
buf, _ := ioutil.ReadAll(m.R.Body) buf, _ := ioutil.ReadAll(m.R.Body)
m.Debug("buf: %+v", string(buf))
xml.NewDecoder(bytes.NewBuffer(buf)).Decode(&data) xml.NewDecoder(bytes.NewBuffer(buf)).Decode(&data)
m.Option("debug", "true")
m.Debug("buf: %+v", string(buf))
m.Debug("data: %+v", data) m.Debug("data: %+v", data)
m.Option("FromUserName", data.FromUserName) m.Option(ACCESS, data.ToUserName)
m.Option("ToUserName", data.ToUserName)
m.Option("CreateTime", data.CreateTime) m.Option("CreateTime", data.CreateTime)
m.Option("MsgId", data.MsgId) m.Option(aaa.USERNAME, data.FromUserName)
m.Option(mdb.TYPE, data.MsgType)
m.Option(mdb.ID, data.MsgId)
m.Option("Event", data.Event) m.Option("Event", data.Event)
m.Option("MsgType", data.MsgType) m.Option("EventKey", data.EventKey)
m.Option("Content", data.Content) m.Option(mdb.TEXT, data.Content)
m.Option("Title", data.Title) m.Option(web.LINK, kit.Select(data.Url, data.PicUrl))
m.Option("Description", data.Description) m.Option(location.LATITUDE, kit.Format("%0.6f", data.Location_X))
m.Option("URL", data.Url) m.Option(location.LONGITUDE, kit.Format("%0.6f", data.Location_Y))
m.Option("URL", data.PicUrl) m.Option(location.SCALE, data.Scale)
m.Option("LocationX", kit.Int(data.Location_X*100000))
m.Option("LocationY", kit.Int(data.Location_Y*100000))
m.Option("Scale", data.Scale)
m.Option("Label", data.Label) m.Option("Label", data.Label)
m.Option("Title", data.Title)
m.Option("MediaId", data.MediaId)
m.Option("Description", data.Description)
m.Option("ScanResult", data.ScanCodeInfo.ScanResult)
} }
const LOGIN = "login" const LOGIN = "login"
func init() { func init() {
web.Index.MergeCommands(ice.Commands{
"/MP_verify_0xp0zkW3fIzIq2Bo.txt": {Actions: aaa.WhiteAction(), Hand: func(m *ice.Message, arg ...string) { m.RenderResult("0xp0zkW3fIzIq2Bo") }},
})
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
web.PP(LOGIN): {Actions: aaa.WhiteAction(), Hand: func(m *ice.Message, arg ...string) { web.PP(LOGIN): {Actions: aaa.WhiteAction(), Hand: func(m *ice.Message, arg ...string) {
if m.Cmdx(ACCESS, CHECK) == "" { if m.Cmdx(ACCESS, aaa.CHECK) == "" {
return
} else if m.Option("echostr") != "" {
m.RenderResult(m.Option("echostr"))
return return
} }
_wx_parse(m) _wx_parse(m)
m.Option(ice.MSG_USERZONE, WX) aaa.SessAuth(m.Options(ice.MSG_USERZONE, WX), kit.Dict(aaa.USERNAME, m.Option(aaa.USERNAME), aaa.USERROLE, aaa.UserRole(m, m.Option(aaa.USERNAME))))
aaa.SessAuth(m, kit.Dict(aaa.USERNAME, m.Option("FromUserName"), aaa.USERROLE, aaa.UserRole(m, m.Option("FromUserName")))) switch m.Option(mdb.TYPE) {
switch m.Option("MsgType") { case gdb.EVENT:
case EVENT: m.Cmdy(EVENTS, strings.ToLower(m.Option("Event")), kit.Split(m.Option("EventKey")))
m.Cmdy(EVENT, m.Option("Event")) case location.LOCATION:
m.Cmdy(location.LOCATION, mdb.CREATE, mdb.TEXT, m.Option("Label"), m.OptionSimple(location.LONGITUDE, location.LATITUDE, location.SCALE))
case TEXT: case TEXT:
if cmds := kit.Split(m.Option("Content")); aaa.Right(m, cmds) { if cmds := kit.Split(m.Option(mdb.TEXT)); aaa.Right(m, cmds) {
m.Cmdy(TEXT, cmds) m.Cmdy(TEXT, ctx.CMDS, cmds)
} else { break
m.Cmdy(MENU, "home")
} }
case mdb.LINK: fallthrough
m.Cmdy(chat.FAVOR, mdb.CREATE, mdb.TYPE, mdb.LINK, mdb.NAME, m.Option("Title"), mdb.TEXT, m.Option("URL")) default:
case wiki.IMAGE: m.Cmdy(chat.FAVOR, mdb.CREATE, mdb.TYPE, m.Option(mdb.TYPE), mdb.NAME, m.Option("Title"), mdb.TEXT, kit.Select(m.Option(mdb.TEXT), m.Option(web.LINK)))
m.Cmdy(chat.FAVOR, mdb.CREATE, mdb.TYPE, wiki.IMAGE, mdb.NAME, m.Option("Title"), mdb.TEXT, m.Option("URL"))
case chat.LOCATION:
m.Cmdy(chat.LOCATION, mdb.CREATE, mdb.TYPE, "", mdb.NAME, m.Option("Label"), mdb.TEXT, m.Option("Label"),
"latitude", m.Option("LocationX"), "longitude", m.Option("LocationY"), "scale", m.Option("Scale"),
)
} }
}}, }},
LOGIN: {Name: "login", Help: "登录", Actions: ice.Actions{ LOGIN: {Name: "login list", Help: "登录", Actions: ice.Actions{
mdb.CREATE: {Name: "create appid appmm token", Hand: func(m *ice.Message, arg ...string) { m.Cmd(ACCESS, LOGIN, arg) }}, mdb.CREATE: {Hand: func(m *ice.Message, arg ...string) { m.Cmd(ACCESS, mdb.CREATE, arg) }},
}}, }, Hand: func(m *ice.Message, arg ...string) { m.Cmdy(ACCESS) }},
}) })
} }

View File

@ -4,43 +4,37 @@ import (
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/web" "shylinux.com/x/icebergs/base/web"
"shylinux.com/x/icebergs/core/wiki"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
func _wx_action(m *ice.Message) (count int) { const (
m.SetResult().RenderResult() SCENE = "scene"
m.Echo(`<xml> RIVER = "river"
<FromUserName><![CDATA[%s]]></FromUserName> STORM = "storm"
<ToUserName><![CDATA[%s]]></ToUserName> )
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
`, m.Option("ToUserName"), m.Option("FromUserName"), m.Option("CreateTime"), "news")
m.Table(func(value ice.Maps) { count++ })
m.Echo(`<ArticleCount>%d</ArticleCount>`, count).Echo(`<Articles>`)
share := m.Cmdx(web.SHARE, mdb.CREATE, mdb.TYPE, web.LOGIN)
m.Table(func(value ice.Maps) {
m.Echo(`<item>
<Title><![CDATA[%s]]></Title>
<Description><![CDATA[%s]]></Description>
<PicUrl><![CDATA[%s]]></PicUrl>
<Url><![CDATA[%s]]></Url>
</item>
`, value[wiki.TITLE], value[wiki.SPARK], value[wiki.IMAGE], kit.MergeURL2(kit.Format(value[wiki.REFER]), "/share/"+share))
}).Echo(`</Articles>`).Echo(`</xml>`)
m.Debug("echo: %v", m.Result())
return
}
const MENU = "menu" const MENU = "menu"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
MENU: {Name: "menu zone id auto insert", Help: "菜单", Actions: ice.MergeActions(ice.Actions{ MENU: {Name: "menu access hash auto", Help: "菜单", Meta: Meta(), Actions: ice.MergeActions(ice.Actions{
mdb.INSERT: {Name: "insert zone=home title=hi refer=hello image"}, mdb.CREATE: {Name: "create scene*=main river*=1,2,3 storm*=1,2,3,4,5,6 type*=click,view,scancode_push,scancode_waitmsg,pic_sysphoto,pic_photo_or_album,pic_weixin,location_select name* text icons space index args"},
}, mdb.ZoneAction(mdb.FIELDS, "time,id,title,refer,image")), Hand: func(m *ice.Message, arg ...string) { mdb.UPDATE: {Name: "update scene*", Hand: func(m *ice.Message, arg ...string) {
if mdb.ZoneSelect(m, arg...); len(arg) > 0 { list := kit.Dict()
_wx_action(m) m.Cmd("", m.Option(ACCESS), func(value ice.Maps) {
if value[SCENE] == m.Option(SCENE) {
key := kit.Keys("button", kit.Int(value[RIVER])-1)
kit.If(value[STORM] != "1", func() { key = kit.Keys(key, "sub_button", kit.Int(value[STORM])-2) })
kit.If(value[mdb.TYPE] == "view", func() { value[mdb.TEXT] = web.MergeLink(m, value[mdb.TEXT]) })
kit.Value(list, key, kit.Dict(mdb.TYPE, value[mdb.TYPE], mdb.NAME, value[mdb.NAME], mdb.KEY, value[mdb.HASH], web.URL, value[mdb.TEXT]))
}
})
m.Echo(kit.Formats(SpidePost(m, MENU_CREATE, web.SPIDE_DATA, kit.Formats(list))))
}},
}, mdb.ExportHashAction(mdb.SHORT, "scene,river,storm", mdb.FIELD, "time,hash,scene,river,storm,type,name,text,icons,space,index,args")), Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 {
m.Cmdy(ACCESS).PushAction("").Option(ice.MSG_ACTION, "")
} else {
mdb.HashSelect(m, arg[1:]...).Sort(mdb.Config(m, mdb.SHORT), ice.STR, ice.INT, ice.INT).Action(mdb.CREATE, mdb.UPDATE)
} }
}}, }},
}) })

31
misc/wx/qrcode.go Normal file
View File

@ -0,0 +1,31 @@
package wx
import (
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/web"
kit "shylinux.com/x/toolkits"
)
const (
EXPIRE_SECONDS = "expire_seconds"
)
const QRCODE = "qrcode"
func init() {
Index.MergeCommands(ice.Commands{
QRCODE: {Name: "qrcode access hash auto", Help: "桌牌", Meta: Meta(), Actions: ice.MergeActions(ice.Actions{
mdb.CREATE: {Name: "create type=QR_STR_SCENE,QR_LIMIT_STR_SCENE name*=1 text* icons expire_seconds=3600 space index* args", Hand: func(m *ice.Message, arg ...string) {
h := mdb.HashCreate(m.Spawn(), arg)
res := SpidePost(m, QRCODE_CREATE, "action_name", m.Option(mdb.TYPE), "action_info.scene.scene_str", h, m.OptionSimple(EXPIRE_SECONDS))
mdb.HashModify(m, mdb.HASH, h, mdb.LINK, kit.Value(res, web.URL), mdb.TIME, m.Time(kit.Format("%ss", kit.Select("60", m.Option(EXPIRE_SECONDS)))))
}},
}, mdb.ExportHashAction(mdb.SHORT, mdb.UNIQ, mdb.FIELD, "time,hash,name,text,icons,space,index,args,type,link")), Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 {
m.Cmdy(ACCESS).PushAction("").Option(ice.MSG_ACTION, "")
} else if mdb.HashSelect(m, arg[1:]...); len(arg) > 1 {
kit.If(m.Time() < m.Append(mdb.TIME), func() { m.PushQRCode(QRCODE, m.Append(mdb.LINK)) })
}
}},
})
}

View File

@ -6,35 +6,29 @@ import (
"shylinux.com/x/icebergs/base/ctx" "shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/web"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
func _wx_reply(m *ice.Message, tmpl string) {
if res, err := kit.Render(mdb.Config(m, nfs.TEMPLATE), m); err == nil {
m.SetResult().RenderResult(string(res))
}
}
const TEXT = "text" const TEXT = "text"
func init() { func init() {
Index.MergeCommands(ice.Commands{ Index.MergeCommands(ice.Commands{
TEXT: {Name: "text", Help: "文本", Actions: ice.MergeActions(ice.Actions{ TEXT: {Help: "文本", Actions: ice.Actions{
MENU: {Name: "menu name=home", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(MENU, m.Option(mdb.NAME)) }}, ctx.CMDS: {Hand: func(m *ice.Message, arg ...string) {
}, ctx.ConfAction(nfs.TEMPLATE, text)), Hand: func(m *ice.Message, arg ...string) { msg := m.Cmd(arg)
if m.Cmdy(arg); m.IsErrNotFound() { kit.If(msg.IsErrNotFound(), func() { msg.SetResult().Cmdy(cli.SYSTEM, arg) })
m.SetResult().Cmdy(cli.SYSTEM, arg) kit.If(msg.Result() == "", func() { msg.TableEcho() })
} m.Cmdy("", msg.Result())
kit.If(m.Result() == "", func() { m.TableEcho() }) }},
_wx_reply(m, m.CommandKey()) web.LINK: {Name: "link link name text icons", Hand: func(m *ice.Message, arg ...string) {
kit.If(m.Option(mdb.ICONS) == "", func() { m.Option(mdb.ICONS, m.Cmdv(ACCESS, m.Option(ACCESS), mdb.ICONS)) })
m.Option(mdb.ICONS, web.ShareLocal(m, m.Option(mdb.ICONS)))
m.Cmdy("", m.OptionDefault(mdb.TEXT, "工具系统"), "link.xml")
}},
}, Hand: func(m *ice.Message, arg ...string) {
m.Echo(nfs.Template(m.Options(mdb.TEXT, arg[0]), kit.Select("welcome.xml", arg, 1))).RenderResult()
m.Debug("text: %v", m.Result())
}}, }},
}) })
} }
var text = `<xml>
<FromUserName><![CDATA[{{.Option "ToUserName"}}]]></FromUserName>
<ToUserName><![CDATA[{{.Option "FromUserName"}}]]></ToUserName>
<CreateTime>{{.Option "CreateTime"}}</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[{{.Result}}]]></Content>
</xml>`

35
misc/wx/users.go Normal file
View File

@ -0,0 +1,35 @@
package wx
import (
"time"
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/mdb"
kit "shylinux.com/x/toolkits"
)
const (
OPENID = "openid"
)
const USERS = "users"
func init() {
Index.MergeCommands(ice.Commands{
USERS: {Name: "users access openid auto", Help: "用户", Meta: Meta(), Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 {
m.Cmdy(ACCESS).PushAction("").Option(ice.MSG_ACTION, "")
} else if m.Options(ACCESS, arg[0]); len(arg) == 1 {
res := SpideGet(m, USER_GET)
kit.For(kit.Value(res, "data.openid"), func(value string) {
res := SpideGet(m, USER_INFO, OPENID, value)
m.Push(mdb.TIME, time.Unix(kit.Int64(kit.Value(res, "subscribe_time")), 0).Format(ice.MOD_TIME))
m.Push("", res, []string{OPENID, "sex", aaa.USERNICK, aaa.LANGUAGE, aaa.PROVINCE, aaa.CITY})
})
m.StatusTimeCountTotal(kit.Value(res, mdb.TOTAL), mdb.NEXT, kit.Value(res, "next_openid"))
} else {
m.Push(ice.FIELDS_DETAIL, SpideGet(m, USER_INFO, OPENID, arg[1]))
}
}},
})
}

View File

@ -8,6 +8,6 @@ import (
const WX = "wx" const WX = "wx"
var Index = &ice.Context{Name: WX, Help: "公众号"} var Index = &ice.Context{Name: WX, Help: "微信公众号"}
func init() { chat.Index.Register(Index, &web.Frame{}) } func init() { chat.Index.Register(Index, &web.Frame{}) }

View File

@ -2,25 +2,35 @@ title "微信公众号"
refer ` refer `
官网 https://weixin.qq.com/ 官网 https://weixin.qq.com/
后台 https://mp.weixin.qq.com/ 后台 https://mp.weixin.qq.com/
测试 https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index
文档 https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Overview.html 文档 https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Overview.html
` `
chapter "配置"
field web.chat.wx.access
field web.chat.wx.qrcode
field web.chat.wx.menu
field web.chat.wx.users
chapter "数据"
field web.chat.favor
field web.chat.location
return
order `
wx.go
wx.shy
access.go
qrcode.go
menu.go
text.go
login.go
events.go
users.go
agent.go
agent.js
`
qrcode `http://weixin.qq.com/r/_B1-Z7TEXOkjrfAE90jq` qrcode `http://weixin.qq.com/r/_B1-Z7TEXOkjrfAE90jq`
chapter "应用"
field "访问" web.chat.wx.access
field "收藏" web.chat.wx.favor
field "菜单" web.chat.wx.menu
field "位置" web.chat.location
chapter "权限"
field "共享" web.share
field "会话" aaa.sess
field "用户" aaa.user
chapter "企业微信" chapter "企业微信"
field "机器人" web.chat.wework.bot field "机器人" web.chat.wework.bot
chapter "项目"
field "源代码" web.code.inner args `usr/icebergs/ misc/wx/login.go`
field "趋势图" web.code.git.trend args `icebergs`
field "架构图" web.code.git.spide args `icebergs`