plugin_utils.go 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. package core
  2. import (
  3. "fmt"
  4. "regexp"
  5. "strings"
  6. "sync"
  7. "time"
  8. "github.com/cdle/sillyplus/mongodb"
  9. "github.com/cdle/sillyplus/utils"
  10. "github.com/dop251/goja"
  11. "github.com/dop251/goja_nodejs/require"
  12. "github.com/robfig/cron/v3"
  13. )
  14. type ScriptUtils struct {
  15. matched bool
  16. ress [][]string
  17. script string
  18. }
  19. func (su *ScriptUtils) match() {
  20. su.ress = regexp.MustCompile(
  21. `(\x20?\*[ ]?@([^\s]+)\s+([^\n]+?)\n)`,
  22. ).FindAllStringSubmatch(su.script, -1)
  23. su.matched = true
  24. }
  25. func (su *ScriptUtils) GetValue(key string) string {
  26. if !su.matched {
  27. su.match()
  28. }
  29. value := ""
  30. for _, res := range su.ress {
  31. if res[2] == key {
  32. value = res[3]
  33. }
  34. }
  35. return value
  36. }
  37. // func Error(err error) interface{} {
  38. // if err != nil {
  39. // return map[string]string{"name": "Error", "message": err.Error()}
  40. // }
  41. // return nil
  42. // }
  43. func (su *ScriptUtils) SetValue(key, value string) {
  44. if !su.matched {
  45. su.match()
  46. }
  47. exists := []string{}
  48. first := ""
  49. for _, res := range su.ress {
  50. if first == "" {
  51. first = res[1]
  52. }
  53. if res[2] == key {
  54. exists = append(exists, res[1])
  55. }
  56. }
  57. if len(exists) != 0 {
  58. for i := range exists {
  59. if i == len(exists)-1 {
  60. su.script = strings.Replace(su.script, exists[i], fmt.Sprintf(" * @%s %s\n", key, value), 1)
  61. } else {
  62. su.script = strings.Replace(su.script, exists[i], "", 1)
  63. }
  64. }
  65. } else {
  66. if first != "" {
  67. su.script = strings.Replace(su.script, first, first+fmt.Sprintf(" * @%s %s\n", key, value), 1)
  68. } else {
  69. su.script = fmt.Sprintf("/**\n%s */\n", fmt.Sprintf(" * @%s %s\n", key, value)) + su.script
  70. }
  71. }
  72. su.match()
  73. }
  74. func (su *ScriptUtils) DeleteValue(key string) {
  75. if !su.matched {
  76. su.match()
  77. }
  78. exists := []string{}
  79. for _, res := range su.ress {
  80. if res[2] == key {
  81. exists = append(exists, res[1])
  82. }
  83. }
  84. if len(exists) != 0 {
  85. for i := range exists {
  86. su.script = strings.Replace(su.script, exists[i], "", 1)
  87. }
  88. }
  89. su.match()
  90. }
  91. var store sync.Map
  92. var crons sync.Map
  93. func CancelPluginCrons(uuid string) {
  94. v, ok := crons.Load(uuid)
  95. if ok {
  96. for _, id := range *v.(*[]cron.EntryID) {
  97. CRON.Remove(id)
  98. }
  99. }
  100. }
  101. func SetPluginMethod(vm *goja.Runtime, uuid string, on_start bool, running func() bool) {
  102. vm.Set("Bucket", func(name string) interface{} {
  103. return JsBucket(vm, name, uuid, on_start)
  104. })
  105. registry := require.NewRegistry(require.WithLoader(mapFileSystemSourceLoader(uuid)))
  106. registry.RegisterNativeModule("crypto", cryptoModule)
  107. registry.RegisterNativeModule("buffer", bufferModule)
  108. if on_start {
  109. var ids = &[]cron.EntryID{}
  110. crons.Store(uuid, ids)
  111. vm.Set("Cron", func() *goja.Object {
  112. o := vm.NewObject()
  113. o.Set("add", func(cron string, f func()) interface{} {
  114. if f == nil {
  115. return map[string]interface{}{
  116. "id": 0,
  117. "error": "未传入handler",
  118. }
  119. }
  120. cron = strings.TrimSpace(cron)
  121. if len(regexp.MustCompile(`\S+`).FindAllString(cron, -1)) == 5 {
  122. cron = "0 " + cron
  123. }
  124. id, err := CRON.AddFunc(cron, func() {
  125. // mutex := GetMutex(uuid)
  126. // mutex.Lock()
  127. // defer mutex.Unlock()
  128. defer func() {
  129. err := recover()
  130. if err != nil {
  131. pluginConsole(uuid).Error("C.AddFunc err: %v", err)
  132. }
  133. }()
  134. f()
  135. })
  136. if err == nil {
  137. *ids = append(*ids, id)
  138. }
  139. return map[string]interface{}{
  140. "id": id,
  141. "error": err,
  142. }
  143. })
  144. o.Set("remove", func(id cron.EntryID) {
  145. CRON.Remove(id)
  146. })
  147. return o
  148. })
  149. vm.Set("gofor", func(running func() bool, handle func()) {
  150. go func() {
  151. for {
  152. if !func() bool {
  153. defer func() {
  154. err := recover()
  155. if err != nil {
  156. pluginConsole(uuid).Error("gofor running error:", err)
  157. }
  158. }()
  159. return running()
  160. }() {
  161. return
  162. }
  163. func() {
  164. defer func() {
  165. err := recover()
  166. if err != nil {
  167. pluginConsole(uuid).Error("gofor error:", err)
  168. }
  169. }()
  170. handle()
  171. }()
  172. }
  173. }()
  174. })
  175. // func (f *Factory) Request(running func() bool, wt interface{}, handles ...func(error, map[string]interface{}, interface{}) interface{}) {
  176. // go func() {
  177. // for {
  178. // if !running() {
  179. // return
  180. // }
  181. // func() {
  182. // defer func() {
  183. // if debug_mode {
  184. // return
  185. // }
  186. // err := recover()
  187. // if err != nil {
  188. // console.Error("Sender(\""+f.platform+"\").request error:", err)
  189. // }
  190. // }()
  191. // request(wt, handles...)
  192. // }()
  193. // }
  194. // }()
  195. // }
  196. }
  197. vm.Set("Express", func() *goja.Object {
  198. o := vm.NewObject()
  199. methods := []string{"get", "post", "delete", "put", "fetch"}
  200. for i := range methods {
  201. method := methods[i]
  202. o.Set(method, func(path string, handles ...func(*Request, *Response)) {
  203. webs = append(webs, Web{
  204. uuid: uuid,
  205. method: strings.ToUpper(method),
  206. path: path,
  207. handles: handles,
  208. })
  209. })
  210. }
  211. o.Set("static", func(path string) {
  212. addStatic(uuid, path)
  213. })
  214. return o
  215. })
  216. registry.Enable(vm)
  217. vm.SetFieldNameMapper(myFieldNameMapper{})
  218. vm.Set("sleep", sleep)
  219. vm.Set("md5", utils.Md5)
  220. vm.Set("image", utils.ToImageQrcode)
  221. vm.Set("video", utils.ToVideoQrcode)
  222. vm.Set("console", &Console{UUID: uuid})
  223. vm.Set("call", func(str string) interface{} {
  224. return RegistFuncs[str]
  225. })
  226. vm.Set("fmt", &Fmt{})
  227. vm.Set("strings", &Strings{
  228. UUID: uuid,
  229. })
  230. // vm.Set("Bucket", BucketJsImpl)
  231. vm.Set("time", &TimeJsImpl{
  232. Second: time.Second,
  233. Minute: time.Minute,
  234. Hour: time.Hour,
  235. Day: time.Hour * 24,
  236. Month: 1,
  237. })
  238. vm.Set("Regexp", Regexp)
  239. vm.Set("Form", func(...interface{}) {
  240. })
  241. vm.Set("url2Base64", Url2Base64)
  242. // 字符串转Base64编码
  243. vm.Set("stringToBase64", stringToBase64)
  244. vm.Set("base64ToString", base64ToString)
  245. vm.Set("Buffer", &BufferObj{vm: vm})
  246. vm.Set("fetch", func(wts ...interface{}) interface{} {
  247. promise, resolve, reject := vm.NewPromise()
  248. go func() {
  249. defer func() {
  250. err := recover()
  251. if err != nil {
  252. o, ok := err.(*goja.Object)
  253. if ok {
  254. (&Console{
  255. UUID: uuid,
  256. }).Error(o.Get("value"))
  257. }
  258. }
  259. }()
  260. obj, err := fetch(vm, uuid, wts...)
  261. if err != nil {
  262. reject(err)
  263. } else {
  264. resolve(obj)
  265. }
  266. }()
  267. return promise
  268. })
  269. vm.Set("request", func(wts ...interface{}) interface{} {
  270. obj, err := fetch(vm, uuid, wts...)
  271. if err != nil {
  272. panic(Error(vm, err))
  273. }
  274. return obj
  275. })
  276. // for _, method := range []string{"get", "post", "delete", "put", "fetch"} {
  277. // vm.Set(method, )
  278. // }
  279. vm.Set("HttpListen", func(method, api string) *goja.Promise {
  280. promise, resolve, reject := vm.NewPromise()
  281. go func() {
  282. func() {
  283. v := recover()
  284. if v != nil {
  285. if err, ok := v.(error); ok {
  286. reject(Error(vm, err))
  287. } else {
  288. reject(Error(vm, fmt.Sprint(v)))
  289. }
  290. }
  291. }()
  292. AddHttpListen(api, strings.ToUpper(method), vm, uuid, resolve, reject)
  293. }()
  294. return promise
  295. })
  296. vm.Set("getReplyMessage", func(plt string, bots_id []string) *goja.Promise {
  297. return GetReplyMessage(vm, plt, bots_id)
  298. })
  299. vm.Set("Script", func(str string) interface{} {
  300. if str == "" {
  301. str = uuid
  302. }
  303. return Script(str)
  304. })
  305. vm.Set("Cache", cache)
  306. vm.Set("Temp", cache)
  307. osjs := getJsOs(vm, running)
  308. vm.Set("os", osjs)
  309. vm.Set("fs", osjs)
  310. vm.Set("forObject", ForeachObject)
  311. vm.Set("MongoClient", func(uri string) interface{} {
  312. return &mongodb.MongoClient{
  313. Uri: uri,
  314. Vm: vm,
  315. }
  316. })
  317. vm.Set("importJs", func(file string) error {
  318. file = strings.Replace(file, ".js", "", -1)
  319. s, id, ok := getPaterner(uuid, file)
  320. if !ok {
  321. panic(Error(vm, "无法通过importJs导入"+file))
  322. }
  323. _, err := vm.RunString(s)
  324. if err != nil {
  325. pluginConsole(id).Error(err)
  326. panic(Error(vm, "通过importJs导入"+file+"错误:"+err.Error()))
  327. }
  328. return nil
  329. })
  330. vm.Set("crypto", &Crypto{
  331. vm: vm,
  332. })
  333. vm.Set("createNickName", CreateNickName)
  334. vm.Set("getListenOnGroups", func(plt string) []string {
  335. groups := []string{}
  336. ListenOnGroups.Range(func(key, value any) bool {
  337. if value == plt {
  338. groups = append(groups, key.(string))
  339. }
  340. return true
  341. })
  342. StaticListenOnGroups.Range(func(key, value any) bool {
  343. if value == plt {
  344. groups = append(groups, key.(string))
  345. }
  346. return true
  347. })
  348. groups = utils.Unique(groups)
  349. return groups
  350. })
  351. }
  352. func EncryptPlugin(script string) string {
  353. res := strings.SplitN(script, "*/\n", 2)
  354. if len(res) != 2 {
  355. // logs.Info(len(res))
  356. return script
  357. }
  358. str, err := EncryptByAes([]byte(res[1]))
  359. if err != nil {
  360. // logs.Info(err)
  361. return script
  362. }
  363. su := ScriptUtils{script: res[0]}
  364. if su.GetValue("encrypt_data") != "" {
  365. return script
  366. }
  367. su.SetValue("encrypt_data", str)
  368. return su.script + "*/\n"
  369. }
  370. func DecryptPlugin(script string) string {
  371. su := ScriptUtils{script: script}
  372. encrypt_data := su.GetValue("encrypt_data")
  373. if encrypt_data == "" {
  374. return script
  375. }
  376. su.DeleteValue("encrypt_data")
  377. str, err := DecryptByAes(encrypt_data)
  378. if err != nil {
  379. return script
  380. }
  381. return fmt.Sprintf("%s%s", su.script, str)
  382. }