func (server *Server) getStats(writer http.ResponseWriter, request *http.Request) *statsResponse { sourceSet := set.New(set.ThreadSafe) metricSet := set.New(set.ThreadSafe) for _, origin := range server.Catalog.GetOrigins() { for _, source := range origin.GetSources() { sourceSet.Add(source.Name) for _, metric := range source.GetMetrics() { metricSet.Add(metric.Name) } } } sourceGroupsCount := 0 metricGroupsCount := 0 for _, group := range server.Library.Groups { if group.Type == library.LibraryItemSourceGroup { sourceGroupsCount++ } else { metricGroupsCount++ } } return &statsResponse{ Origins: len(server.Catalog.GetOrigins()), Sources: sourceSet.Size(), Metrics: metricSet.Size(), Graphs: len(server.Library.Graphs), Collections: len(server.Library.Collections), SourceGroups: sourceGroupsCount, MetricGroups: metricGroupsCount, } }
func (server *Server) serveMetricList(writer http.ResponseWriter, request *http.Request) { var offset, limit int if response, status := server.parseListRequest(writer, request, &offset, &limit); status != http.StatusOK { server.serveResponse(writer, response, status) return } originName := request.FormValue("origin") sourceName := request.FormValue("source") sourceSet := set.New(set.ThreadSafe) if strings.HasPrefix(sourceName, library.LibraryGroupPrefix) { for _, entryName := range server.Library.ExpandSourceGroup( strings.TrimPrefix(sourceName, library.LibraryGroupPrefix), ) { sourceSet.Add(entryName) } } else if sourceName != "" { sourceSet.Add(sourceName) } metricSet := set.New(set.ThreadSafe) for _, origin := range server.Catalog.GetOrigins() { if originName != "" && origin.Name != originName { continue } for _, source := range origin.GetSources() { if sourceName != "" && sourceSet.IsEmpty() || !sourceSet.IsEmpty() && !sourceSet.Has(source.Name) { continue } for _, metric := range source.GetMetrics() { if request.FormValue("filter") != "" && !utils.FilterMatch(request.FormValue("filter"), metric.Name) { continue } metricSet.Add(metric.Name) } } } response := &listResponse{ list: StringListResponse(set.StringSlice(metricSet)), offset: offset, limit: limit, } server.applyResponseLimit(writer, request, response) server.serveResponse(writer, response.list, http.StatusOK) }
// toSet converts a slice of strings into a set func toSet(s []string) set.Interface { if s == nil { return set.New(set.NonThreadSafe) } is := make([]interface{}, len(s)) for i, s := range s { is[i] = s } set := set.New(set.NonThreadSafe) set.Add(is...) return set }
func LoadConf() { var err error conf, err = yaml.ReadFile("botconf.yaml") if err != nil { log.Panic(err) } Categories = List2SliceInConf("catagoris") CategoriesSet = set.New(set.NonThreadSafe) Groups = []Group{} for _, v := range Categories { CategoriesSet.Add(v) for _, i := range List2SliceInConf(v) { reg := regexp.MustCompile("^(.+) (http(s)?://(.*))$") strs := reg.FindAllStringSubmatch(i, -1) if !reg.MatchString(i) { Groups = append(Groups, Group{GroupName: i, GroupURL: ""}) } if len(strs) > 0 { Groups = append(Groups, Group{GroupName: strs[0][1], GroupURL: strs[0][2]}) } } } }
func (server *Server) serveOriginList(writer http.ResponseWriter, request *http.Request) { var offset, limit int if response, status := server.parseListRequest(writer, request, &offset, &limit); status != http.StatusOK { server.serveResponse(writer, response, status) return } originSet := set.New(set.ThreadSafe) for _, origin := range server.Catalog.GetOrigins() { if request.FormValue("filter") == "" || utils.FilterMatch(request.FormValue("filter"), origin.Name) { originSet.Add(origin.Name) } } response := &listResponse{ list: StringListResponse(set.StringSlice(originSet)), offset: offset, limit: limit, } server.applyResponseLimit(writer, request, response) server.serveResponse(writer, response.list, http.StatusOK) }
func (server *Server) serveSource(writer http.ResponseWriter, request *http.Request) { name := routeTrimPrefix(request.URL.Path, urlCatalogPath+"sources") if name == "" { server.serveSourceList(writer, request) return } else if response, status := server.parseShowRequest(writer, request); status != http.StatusOK { server.serveResponse(writer, response, status) return } originSet := set.New(set.ThreadSafe) for _, origin := range server.Catalog.GetOrigins() { if origin.SourceExists(name) { originSet.Add(origin.Name) } } if originSet.Size() == 0 { server.serveResponse(writer, serverResponse{mesgResourceNotFound}, http.StatusNotFound) return } origins := set.StringSlice(originSet) sort.Strings(origins) response := SourceResponse{ Name: name, Origins: origins, } server.serveResponse(writer, response, http.StatusOK) }
func init() { rc = redis.NewClient(&redis.Options{ Addr: "localhost:6379", }) // Init categories categories = []string{ "Linux", "Programming", "Software", "影音", "科幻", "ACG", "IT", "社区", "闲聊", "资源", "同城", "Others", } categoriesSet = set.New(set.NonThreadSafe) for _, v := range categories { categoriesSet.Add(v) } LoadConf() botapi, _ := conf.Get("botapi") vimTipsCache, _ := conf.GetInt("vimTipsCache") hitokotoCache, _ := conf.GetInt("hitokotoCache") vimtips = new(Tips).GetChan(int(vimTipsCache)) hitokoto = new(Hitokoto).GetChan(int(hitokotoCache)) sticker = RandSticker(rc) var err error bot, err = tgbotapi.NewBotAPI(botapi) if err != nil { log.Panic(err) } u := tgbotapi.NewUpdate(0) u.Timeout = 60 bot.UpdatesChan(u) }
func (server *Server) serveMetric(writer http.ResponseWriter, request *http.Request) { metricName := routeTrimPrefix(request.URL.Path, urlCatalogPath+"metrics") if metricName == "" { server.serveMetricList(writer, request) return } else if response, status := server.parseShowRequest(writer, request); status != http.StatusOK { server.serveResponse(writer, response, status) return } originSet := set.New(set.ThreadSafe) sourceSet := set.New(set.ThreadSafe) for _, origin := range server.Catalog.GetOrigins() { for _, source := range origin.GetSources() { if source.MetricExists(metricName) { originSet.Add(origin.Name) sourceSet.Add(source.Name) } } } if originSet.Size() == 0 { server.serveResponse(writer, serverResponse{mesgResourceNotFound}, http.StatusNotFound) return } origins := set.StringSlice(originSet) sort.Strings(origins) sources := set.StringSlice(sourceSet) sort.Strings(sources) response := MetricResponse{ Name: metricName, Origins: origins, Sources: sources, } server.serveResponse(writer, response, http.StatusOK) }
func (s *Server) handleAPIHosts(c *gin.Context) { hs := set.New(set.ThreadSafe) // Get hosts list hosts, _ := s.poller.GetHosts() for _, h := range hosts { hs.Add(h.Name) } // Get unique set of hosts names result := set.StringSlice(hs) sort.Strings(result) c.Header("Cache-Control", "private, max-age=0") c.JSON(http.StatusOK, result) }
func GetQuestions() []Question { var result []Question questions := List2SliceInConf("questions") for _, v := range questions { qs := strings.Split(v, "|") question := qs[0] answers := strings.Split(qs[1], ";") s := set.New(set.ThreadSafe) for _, v := range answers { s.Add(v) } result = append(result, Question{question, s}) } return result }
func GetQuestions(config *yaml.File, text string) []Question { var result []Question questions := YamlList2Slice(config, text) for _, v := range questions { qs := strings.Split(v, "|") question := qs[0] answers := strings.Split(qs[1], ";") s := set.New(set.ThreadSafe) for _, v := range answers { s.Add(v) } result = append(result, Question{question, s}) } return result }
func (g *GitHub) GetNotes(owner string, repo string, milestoneID string) (*Note, error) { opt := github.IssueListByRepoOptions{Milestone: milestoneID, State: "all"} note := &Note{} issues, _, err := g.ListByRepo(owner, repo, &opt) if err != nil { return note, err } note.Mentioned = set.New(set.NonThreadSafe) //var buf bytes.Buffer for _, issue := range issues { summary := fmt.Sprintf("- %v [%s #%d / %s](%s)\n", issue.Labels, repo, *issue.Number, *issue.Title, *issue.HTMLURL) note.IssueSummary += summary note.RepoVersion = fmt.Sprintf("- [%s:%s]()\n", repo, *issue.Milestone.Title) // TODO: check Mentions m := getMensionedPersons(issue.Body) if m != "" { ids := strings.Split(m, " ") // fmt.Println("******** m : ", m) // fmt.Println("******** ids : ", ids) for i := range ids { id := strings.TrimRight(ids[i], ",") note.Mentioned.Add(id) // fmt.Println("******** id : ", id) } } // TODO 하루 전 날로 나올까? (지금은 +1 해줬다) //note.MilestoneDate = fmt.Sprintf("- %s:%s 10:00\n", repo, issue.Milestone.DueOn.Format("2006-01-02")) note.MilestoneDate = fmt.Sprintf("- %s:%s 10:00\n", repo, issue.Milestone.DueOn.AddDate(0, 0, 1).Format("2006-01-02")) //note.DeployDate = issue.Milestone.DueOn.Format("2006-01-02") note.DeployDate = issue.Milestone.DueOn.AddDate(0, 0, 1).Format("2006-01-02") //fmt.Println("DeployDate ", note.DeployDate) } //fmt.Println("after mention:", buf.String()) return note, nil }
// TODO: classify by Labels func main() { gitHubURL := baseGitHubURL url := os.Getenv("GITHUB_URL") if url != "" { gitHubURL = url } clientID := os.Getenv("CLIENT_ID") clientSecret := os.Getenv("CLIENT_SECRET") owner := os.Getenv("OWNER") milestoneID := os.Getenv("MILESTONE_ID") repos := os.Getenv("REPOS") // check arguments.. if gitHubURL == "" || owner == "" || milestoneID == "" || repos == "" { fmt.Println(getUsage()) os.Exit(0) } var note Note hub := GitHub{ apiURL: gitHubURL, user: clientID, password: clientSecret, } // TODO: magic string note.Title = "통합검색 배포 안내드립니다." note.Mentioned = set.New(set.NonThreadSafe) for _, repo := range strings.Split(repos, ":") { n, err := hub.GetNotes(owner, repo, milestoneID) if err != nil { log.Fatalln("error: %v", err) } note.Merge(n) } note.MentionedPersons = fmt.Sprintf("- %v", strings.Trim(note.Mentioned.String(), "[]")) t := template.Must(template.New("note").Parse(noteTemplate)) err := t.Execute(os.Stdout, note) if err != nil { log.Fatalln("template error:", err) } }
func LoadConf() { var err error conf, err = yaml.ReadFile("botconf.yaml") if err != nil { log.Panic(err) } Categories = List2SliceInConf("catagoris") CategoriesSet = set.New(set.NonThreadSafe) Groups = []string{} for _, v := range Categories { CategoriesSet.Add(v) for _, i := range List2SliceInConf(v) { if i != "\\n" { Groups = append(Groups, i) } } } }
func (s *Server) handleAPIGroups(c *gin.Context) { gs := set.New(set.ThreadSafe) // Get unique sets of groups names hosts, _ := s.poller.GetHosts() for _, h := range hosts { for _, g := range h.Groups { gs.Add(g) } for _, s := range h.Services { for _, g := range s.Groups { gs.Add(g) } } } result := set.StringSlice(gs) natsort.Sort(result) c.Header("Cache-Control", "private, max-age=0") c.JSON(http.StatusOK, result) }
// NewPoller returns a new poller instance func NewPoller(c Config) *Poller { p := &Poller{ config: c, Workers: make([]*Worker, 0), wg: &sync.WaitGroup{}, } logger.Info("poller", "starting poller workers") names := set.New(set.ThreadSafe) for _, n := range c.Nodes { if n.Name == "" { logger.Error("poller", "missing mandatory `name' node parameter") continue } else if n.Address == "" { logger.Error("poller", "missing mandatory `remote_addr' node parameter") continue } else if names.Has(n.Name) { logger.Error("poller", "duplicate name `%s' found in node definition", n.Name) continue } w := NewWorker(n, p.wg) p.Workers = append(p.Workers, w) p.wg.Add(1) go w.Start() w.Refresh() names.Add(n.Name) } return p }
func (server *Server) serveSourceList(writer http.ResponseWriter, request *http.Request) { var offset, limit int if response, status := server.parseListRequest(writer, request, &offset, &limit); status != http.StatusOK { server.serveResponse(writer, response, status) return } originName := request.FormValue("origin") sourceSet := set.New(set.ThreadSafe) for _, origin := range server.Catalog.GetOrigins() { if originName != "" && origin.Name != originName { continue } for _, source := range origin.GetSources() { if request.FormValue("filter") != "" && !utils.FilterMatch(request.FormValue("filter"), source.Name) { continue } sourceSet.Add(source.Name) } } response := &listResponse{ list: StringListResponse(set.StringSlice(sourceSet)), offset: offset, limit: limit, } server.applyResponseLimit(writer, request, response) server.serveResponse(writer, response.list, http.StatusOK) }
func init() { var err error // Init categories categories = []string{ "Linux", "Programming", "Software", "影音", "科幻", "ACG", "IT", "社区", "闲聊", "资源", "同城", "Others", } categoriesSet = set.New(set.NonThreadSafe) for _, v := range categories { categoriesSet.Add(v) } loge.Level = logrus.DebugLevel LoadConf() botapi, _ := conf.Get("botapi") redisPass, _ := conf.Get("redisPass") vimTipsCache, _ := conf.GetInt("vimTipsCache") hitokotoCache, _ := conf.GetInt("hitokotoCache") vimtips = new(Tips).GetChan(int(vimTipsCache)) hitokoto = new(Hitokoto).GetChan(int(hitokotoCache)) papertrailURL, _ := conf.Get("papertrailUrl") papertrailPort, _ := conf.GetInt("papertrailPort") rc = redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: redisPass, }) sticker = RandSticker(rc) //logger hook, err := logrus_papertrail.NewPapertrailHook( papertrailURL, int(papertrailPort), "nyan") if err != nil { loge.Println(err) } else { loge.Hooks.Add(hook) } //bot init bot, err = tgbotapi.NewBotAPI(botapi) if err != nil { loge.Panic(err) } if runMode == "debug" { hook := tgbotapi.NewWebhook("") bot.SetWebhook(hook) u := tgbotapi.NewUpdate(0) u.Timeout = 60 bot.UpdatesChan(u) } else { hook := tgbotapi.NewWebhookWithCert("https://jqs7.com:8443/"+bot.Token, "crt.pem") bot.SetWebhook(hook) bot.ListenForWebhook("/" + bot.Token) go http.ListenAndServeTLS(":8443", "crt.pem", "key.pem", nil) } initRss() MIndex() dailySave() scheduler.Every().Day().At("00:05").Run(dailySave) go GinServer() }
// Refresh triggers a full connector data update. func (c *RRDConnector) Refresh(originName string, outputChan chan<- *catalog.Record) error { // Search for files and parse their path for source/metric pairs walkFunc := func(filePath string, fileInfo os.FileInfo, err error) error { var sourceName, metricName string // Report errors if err != nil { logger.Log(logger.LevelWarning, "connector", "rrd[%s]: error while walking: %s", c.name, err) return nil } // Skip non-files mode := fileInfo.Mode() & os.ModeType if mode != 0 { return nil } // Get pattern matches m, err := matchSeriesPattern(c.re, strings.TrimPrefix(filePath, c.path+"/")) if err != nil { logger.Log(logger.LevelInfo, "connector", "rrd[%s]: file `%s' does not match pattern, ignoring", c.name, filePath) return nil } sourceName, metricName = m[0], m[1] if _, ok := c.metrics[sourceName]; !ok { c.metrics[sourceName] = make(map[string]*rrdMetric) } // Extract metric information from .rrd file info, err := rrd.Info(filePath) if err != nil { logger.Log(logger.LevelWarning, "connector", "rrd[%s]: %s", c.name, err) return nil } // Extract consolidation functions list cfSet := set.New(set.ThreadSafe) if cf, ok := info["rra.cf"].([]interface{}); ok { for _, entry := range cf { if name, ok := entry.(string); ok { cfSet.Add(name) } } } cfList := set.StringSlice(cfSet) if _, ok := info["ds.index"]; ok { indexes, ok := info["ds.index"].(map[string]interface{}) if !ok { return nil } for dsName := range indexes { for _, cfName := range cfList { metricFullName := metricName + "/" + dsName + "/" + strings.ToLower(cfName) c.metrics[sourceName][metricFullName] = &rrdMetric{ Dataset: dsName, FilePath: filePath, Step: time.Duration(info["step"].(uint)) * time.Second, Cf: cfName, } outputChan <- &catalog.Record{ Origin: originName, Source: sourceName, Metric: metricFullName, Connector: c, } } } } return nil } if err := utils.WalkDir(c.path, walkFunc); err != nil { return err } return nil }
func (s *Server) handleAPISearch(c *gin.Context) { var hgs, sgs set.Interface // Parse search query q := searchQuery{} if err := c.BindJSON(&q); err != nil { fmt.Printf("ERROR: unable to parse JSON data: %s\n", err) c.JSON(http.StatusBadRequest, nil) return } // Get groups set gs := set.New(set.ThreadSafe) for _, g := range q.Groups { gs.Add(g) } // Prepare hosts response result := make(searchResponseList, 0) hosts, _ := s.poller.GetHosts() for _, h := range hosts { // Check for node and name filters if len(q.Nodes) > 0 && slice.StringIndexOf(q.Nodes, h.Catalog.Worker.Config.Name) == -1 || q.Filter != "" && !strings.Contains(strings.ToLower(h.Name), strings.ToLower(q.Filter)) { continue } // Prepare search response sr := searchResponse{ hostResponse: hostResponse{ Name: h.Name, State: h.State, StateChanged: h.StateChanged, Comments: make(commentList, 0), Links: h.Links, }, Services: make(serviceResponseList, 0), } // Fill comments and sort them by date for _, c := range h.Comments { if c.Type == poller.CommentTypeDowntime { // Check for downtimes filter if !q.Downtimes { goto nextHost } sr.hostResponse.InDowntime = true } else if c.Type == poller.CommentTypeAcknowledgement { // Check for acknowledges filter if !q.Acknowledges { goto nextHost } sr.hostResponse.Acknowledged = true } sr.hostResponse.Comments = append(sr.Comments, commentEntry{ Author: c.Author, Content: c.Content, Type: c.Type, Date: c.Date, }) } sort.Sort(sr.Comments) // Add extra node information if h.Catalog.Worker.Config.Label != "" { sr.Node = h.Catalog.Worker.Config.Label } else { sr.Node = h.Catalog.Worker.Config.Name } // Prepare set for groups filtering if !gs.IsEmpty() { hgs = set.New(set.ThreadSafe) for _, g := range h.Groups { hgs.Add(g) } } // Fill services list for _, svc := range h.Services { // Check for states filter if len(q.States) > 0 && slice.Int64IndexOf(q.States, svc.State) == -1 { continue } // Check for groups filter if !gs.IsEmpty() { if len(svc.Groups) > 0 { sgs = set.New(set.ThreadSafe) for _, g := range svc.Groups { sgs.Add(g) } } else { sgs = hgs } if set.Intersection(gs, sgs).IsEmpty() { continue } } svcr := serviceResponse{ Name: svc.Name, State: svc.State, StateChanged: svc.StateChanged, Comments: make(commentList, 0), Links: svc.Links, Output: svc.Output, } // Fill comments and sort them by date for _, c := range svc.Comments { if c.Type == poller.CommentTypeDowntime { // Check for downtimes filter if !q.Downtimes { goto nextService } svcr.InDowntime = true } else if c.Type == poller.CommentTypeAcknowledgement { // Check for acknowledges filter if !q.Acknowledges { goto nextService } svcr.Acknowledged = true } svcr.Comments = append(svcr.Comments, commentEntry{ Author: c.Author, Content: c.Content, Type: c.Type, Date: c.Date, }) } sort.Sort(svcr.Comments) sr.Services = append(sr.Services, svcr) nextService: } if len(sr.Services) == 0 { continue } sort.Sort(sr.Services) result = append(result, sr) nextHost: } sort.Sort(result) c.Header("Cache-Control", "private, max-age=0") c.JSON(http.StatusOK, result) }
func Test(t *testing.T) { convey.Convey("YamlList2String Test", t, func() { conf, err := yaml.ReadFile("botconf_test.yaml") convey.So(err, convey.ShouldBeNil) convey.So(YamlList2String(conf, "listTest"), convey.ShouldEqual, "1\n2\n\n3") }) convey.Convey("Questions Test", t, func() { conf, err := yaml.ReadFile("botconf_test.yaml") convey.So(err, convey.ShouldBeNil) s1 := set.New(set.ThreadSafe) s2 := set.New(set.ThreadSafe) s1.Add("A1", "A2", "A3") s2.Add("A4", "A5", "A6") result := []Question{Question{"Q1", s1}, Question{"Q2", s2}} convey.So(GetQuestions(conf, "questionsTest"), convey.ShouldHaveSameTypeAs, result) convey.So(GetQuestions(conf, "questionsTest"), convey.ShouldResemble, result) }) convey.Convey("To2dSlice Test", t, func() { in := []string{"1", "2", "3", "4", "5"} out := [][]string{[]string{"1", "2", "3"}, []string{"4", "5"}} convey.So(To2dSlice(in, 3, 2), convey.ShouldResemble, out) }) convey.Convey("Vim-Tips Test", t, func() { t := <-new(Tips).GetChan(1) convey.So(t.Comment, convey.ShouldNotBeBlank) convey.So(t.Content, convey.ShouldNotBeBlank) }) convey.Convey("Hitokoto Test", t, func() { h := <-new(Hitokoto).GetChan(1) convey.So(h.Hitokoto, convey.ShouldNotBeBlank) convey.So(h.Source, convey.ShouldNotBeBlank) }) convey.Convey("Google Test", t, func() { convey.So(Google("hey"), convey.ShouldEqual, "HEY!\nhttp://hey.com/\nhey - Wiktionary\nhttps://en.wiktionary.org/wiki/hey\n"+ "Hey | Define Hey at Dictionary.com\nhttp://dictionary.reference.com/browse/hey\n") }) convey.Convey("Base64 Test", t, func() { convey.So(E64("Hello"), convey.ShouldEqual, "SGVsbG8=") convey.So(D64("sdjaikdbsa"), convey.ShouldEqual, "解码系统出现故障,请查看弹药是否填充无误") convey.So(D64("SGVsbG8="), convey.ShouldEqual, "Hello") }) convey.Convey("Translate Test", t, func() { conf, err := yaml.ReadFile("botconf_test.yaml") convey.So(err, convey.ShouldBeNil) convey.So(BaiduTranslate("123", "Hello"), convey.ShouldEqual, "大概男盆友用错API Key啦,大家快去蛤他!σ`∀´)`") key, err := conf.Get("baiduTransKey") convey.So(err, convey.ShouldBeNil) convey.So(BaiduTranslate(key, "你好"), convey.ShouldEqual, "Hello") convey.So(BaiduTranslate(key, "Hello"), convey.ShouldEqual, "你好") }) }
// Where the magic happens. func main() { // Parse command line flags flag.BoolVar(&printArray, "array", false, "Output an array of path lengths rather than all paths.") flag.BoolVar(&printProgress, "progress", false, "Display notification when a new int has been found.") flag.IntVar(&goal, "goal", 100, "How many integers should be found before aborting.") flag.Parse() // Create the initial set and a set to store all found numbers initialNumbers := set.New(4) allNumbers := set.New() // Use a map to store the numbers we're interested in crunchedNumbers := make(map[int]*crunch.CrunchedNumber) // Create two channels, one 'small' numbers and one for big ones channelBig := make(chan *crunch.CrunchedNumber, 100) channelSmall := make(chan *crunch.CrunchedNumber, 100) // Add the first number to the small channel for !initialNumbers.IsEmpty() { x := initialNumbers.Pop() temp := x.(int) i := int64(temp) firstNumber := &crunch.CrunchedNumber{big.NewInt(i), ""} channelSmall <- firstNumber } // Loop while less then 100 values have been found found := 0 for found < goal { select { case nextNumber := <-channelSmall: // Convert it to an int and check whether it is in the 0-100 range // If so, add it to the crunchedNumbers map temp := nextNumber.N.Int64() if 0 < temp && temp <= 100 { value, ok := crunchedNumbers[int(temp)] if !ok { found++ if printProgress { fmt.Println(nextNumber.N, " as element : ", found) } crunchedNumbers[int(temp)] = nextNumber } else { oldNumber := strings.NewReader(value.How) newNumber := strings.NewReader(nextNumber.How) if oldNumber.Len() > newNumber.Len() { crunchedNumbers[int(temp)] = nextNumber } } } // If it has already been found, skip it, else add it to numbers found if allNumbers.Has(nextNumber.N.String()) { continue } allNumbers.Add(nextNumber.N.String()) go crunch.AddFactorial(nextNumber, channelBig, channelSmall) crunch.AddSqrt(nextNumber, channelBig, channelSmall) case nextNumber := <-channelBig: // If it has already been found, skip it, else add it to numbers found if allNumbers.Has(nextNumber.N.String()) { continue } allNumbers.Add(nextNumber.N.String()) crunch.AddSqrt(nextNumber, channelBig, channelSmall) } } // End of program foundSlice := make([]int, 100) for x := 0; x < 100; x++ { value, ok := crunchedNumbers[x+1] if ok { path, pathLength := PrintRoute(value) if !printArray { fmt.Println(x+1, path) } foundSlice[x] = pathLength } else { foundSlice[x] = 0 } } if printArray { // Print all found pathlengths at the end, wee bit hacky fmt.Print("[") for i, v := range foundSlice { fmt.Print(v) if i != 99 { fmt.Print(", ") } } fmt.Println("]") } }
func (server *Server) serveCollectionList(writer http.ResponseWriter, request *http.Request) { var ( collection *library.Collection collectionStack []*library.Collection items CollectionListResponse offset, limit int ) if response, status := server.parseListRequest(writer, request, &offset, &limit); status != http.StatusOK { server.serveResponse(writer, response, status) return } // Check for item exclusion excludeSet := set.New(set.ThreadSafe) if request.FormValue("exclude") != "" { if item, err := server.Library.GetItem(request.FormValue("exclude"), library.LibraryItemCollection); err == nil { collectionStack = append(collectionStack, item.(*library.Collection)) } for len(collectionStack) > 0 { collection, collectionStack = collectionStack[0], collectionStack[1:] excludeSet.Add(collection.ID) collectionStack = append(collectionStack, collection.Children...) } } // Fill collections list items = make(CollectionListResponse, 0) for _, collection := range server.Library.Collections { if request.FormValue("parent") == "null" && collection.Parent != nil || request.FormValue("parent") != "" && request.FormValue("parent") != "null" && (collection.Parent == nil || collection.Parent.ID != request.FormValue("parent")) { continue } if request.FormValue("filter") != "" && !utils.FilterMatch(request.FormValue("filter"), collection.Name) { continue } // Skip excluded items if excludeSet.Has(collection.ID) { continue } collectionItem := &CollectionResponse{ ItemResponse: ItemResponse{ ID: collection.ID, Name: collection.Name, Description: collection.Description, Modified: collection.Modified.Format(time.RFC3339), }, Options: collection.Options, HasChildren: len(collection.Children) > 0, } if collection.Parent != nil { collectionItem.Parent = &collection.Parent.ID } items = append(items, collectionItem) } response := &listResponse{ list: items, offset: offset, limit: limit, } server.applyResponseLimit(writer, request, response) server.serveResponse(writer, response.list, http.StatusOK) }
func (library *Library) expandGroup(name string, groupType int, sourceName string) []string { item, err := library.GetItemByName(name, groupType) if err != nil { logger.Log(logger.LevelError, "library", "expand group: unknown group `%s': %s", name, err) return []string{} } // Launch expansion goroutine itemSet := set.New(set.ThreadSafe) itemChan := make(chan [2]string) itemWg := &sync.WaitGroup{} go func(itemSet set.Interface, itemChan chan [2]string, itemWg *sync.WaitGroup) { var re *regexp.Regexp itemWg.Add(1) for entry := range itemChan { if strings.HasPrefix(entry[0], LibraryMatchPrefixGlob) { if ok, _ := path.Match(strings.TrimPrefix(entry[0], LibraryMatchPrefixGlob), entry[1]); !ok { continue } } else if strings.HasPrefix(entry[0], LibraryMatchPrefixRegexp) { re = regexp.MustCompile(strings.TrimPrefix(entry[0], LibraryMatchPrefixRegexp)) if !re.MatchString(entry[1]) { continue } } else if entry[0] != entry[1] { continue } itemSet.Add(entry[1]) } itemWg.Done() }(itemSet, itemChan, itemWg) // Parse group entries for patterns group := item.(*Group) for _, entry := range group.Entries { if groupType == LibraryItemSourceGroup { origin, err := library.Catalog.GetOrigin(entry.Origin) if err != nil { logger.Log(logger.LevelError, "library", "%s", err) continue } for _, source := range origin.GetSources() { itemChan <- [2]string{entry.Pattern, source.Name} } } else { source, err := library.Catalog.GetSource(entry.Origin, sourceName) if err != nil { logger.Log(logger.LevelError, "library", "%s", err) continue } for _, metric := range source.GetMetrics() { itemChan <- [2]string{entry.Pattern, metric.Name} } } } close(itemChan) itemWg.Wait() result := set.StringSlice(itemSet) sort.Strings(result) return result }
func (server *Server) serveGraphList(writer http.ResponseWriter, request *http.Request) { var ( items GraphListResponse offset, limit int ) if response, status := server.parseListRequest(writer, request, &offset, &limit); status != http.StatusOK { server.serveResponse(writer, response, status) return } graphSet := set.New(set.ThreadSafe) // Filter on collection if any if request.FormValue("collection") != "" { item, err := server.Library.GetItem(request.FormValue("collection"), library.LibraryItemCollection) if os.IsNotExist(err) { server.serveResponse(writer, serverResponse{mesgResourceNotFound}, http.StatusNotFound) return } else if err != nil { logger.Log(logger.LevelError, "server", "%s", err) server.serveResponse(writer, serverResponse{mesgUnhandledError}, http.StatusInternalServerError) return } collection := item.(*library.Collection) for _, graph := range collection.Entries { graphSet.Add(graph.ID) } } // Fill graphs list items = make(GraphListResponse, 0) // Flag for listing only graph templates listType := request.FormValue("type") if listType == "" { listType = "all" } else if listType != "raw" && listType != "template" && listType != "all" { logger.Log(logger.LevelWarning, "server", "unknown list type: %s", listType) server.serveResponse(writer, serverResponse{mesgRequestInvalid}, http.StatusBadRequest) return } for _, graph := range server.Library.Graphs { // Depending on the template flag, filter out either graphs or graph templates if request.FormValue("type") != "all" && (graph.Template && listType == "raw" || !graph.Template && listType == "template") { continue } // Filter out graphs that don't belong in the targeted collection if !graphSet.IsEmpty() && !graphSet.Has(graph.ID) { continue } if request.FormValue("filter") != "" && !utils.FilterMatch(request.FormValue("filter"), graph.Name) { continue } // If linked graph, expand the templated description field description := graph.Description if graph.Link != "" { item, err := server.Library.GetItem(graph.Link, library.LibraryItemGraph) if err != nil { logger.Log(logger.LevelError, "server", "graph template not found") } else { graphTemplate := item.(*library.Graph) if description, err = expandStringTemplate( graphTemplate.Description, graph.Attributes, ); err != nil { logger.Log(logger.LevelError, "server", "failed to expand graph description: %s", err) } } } items = append(items, &GraphResponse{ ItemResponse: ItemResponse{ ID: graph.ID, Name: graph.Name, Description: description, Modified: graph.Modified.Format(time.RFC3339), }, Link: graph.Link, Template: graph.Template, }) } response := &listResponse{ list: items, offset: offset, limit: limit, } server.applyResponseLimit(writer, request, response) server.serveResponse(writer, response.list, http.StatusOK) }
func main() { rc := redis.NewClient(&redis.Options{ Addr: "localhost:6379", }) defer rc.Close() // Init categories categories := []string{ "Linux", "Programming", "Software", "影音", "科幻", "ACG", "IT", "社区", "闲聊", "资源", "同城", "Others", } categoriesSet := set.New(set.NonThreadSafe) for _, v := range categories { categoriesSet.Add(v) } conf, err := yaml.ReadFile("botconf.yaml") if err != nil { log.Panic(err) } botapi, _ := conf.Get("botapi") baiduAPI, _ := conf.Get("baiduTransKey") vimTipsCache, _ := conf.GetInt("vimTipsCache") bot, err := tgbotapi.NewBotAPI(botapi) if err != nil { log.Panic(err) } botname := bot.Self.UserName u := tgbotapi.NewUpdate(0) u.Timeout = 60 updates, err := bot.UpdatesChan(u) tips := VimTipsChan(int(vimTipsCache)) for update := range updates { // Ignore Outdated Updates if time.Since(time.Unix(int64(update.Message.Date), 0)) > time.Hour { continue } u := Updater{ redis: rc, bot: bot, update: update, conf: conf, } // Logger startWithSlash, _ := regexp.MatchString("^/", update.Message.Text) atBot, _ := regexp.MatchString("@"+botname, update.Message.Text) if update.Message.Chat.ID > 0 || startWithSlash || atBot { log.Printf("[%d](%s) -- [%s] -- %s", update.Message.Chat.ID, update.Message.Chat.Title, update.Message.From.UserName, update.Message.Text, ) } // Auto Rule When New Member Join Group if update.Message.NewChatParticipant.ID != 0 { chatIDStr := strconv.Itoa(u.update.Message.Chat.ID) if u.redis.Exists("tgGroupAutoRule:" + chatIDStr).Val() { go func() { msg := tgbotapi.NewMessage(update.Message.NewChatParticipant.ID, "欢迎加入 "+update.Message.Chat.Title+"\n 以下是群组规则:") bot.SendMessage(msg) u.Rule(update.Message.NewChatParticipant.ID) }() } } s := strings.FieldsFunc(update.Message.Text, func(r rune) bool { switch r { case '\t', '\v', '\f', '\r', ' ', 0xA0: return true } return false }) if len(s) > 0 { switch s[0] { case "/help", "/start", "/help@" + botname, "/start@" + botname: go u.Start() case "/rules", "/rules@" + botname: go u.Rule(update.Message.Chat.ID) case "/about", "/about@" + botname: go u.BotReply(YamlList2String(conf, "about")) case "/other_resources", "/other_resources@" + botname: go u.BotReply(YamlList2String(conf, "其他资源")) case "/subscribe", "/subscribe@" + botname: go u.Subscribe() case "/unsubscribe", "/unsubscribe@" + botname: go u.UnSubscribe() case "/autorule": go u.AutoRule() case "/groups", "/groups@" + botname: go u.Groups(categories, 3, 5) case "/vimtips": t := <-tips go u.BotReply(t.Content + "\n" + t.Comment) case "/setrule": if len(s) >= 2 { rule := strings.Join(s[1:], " ") go u.SetRule(rule) } case "/e64": if len(s) >= 2 { in := strings.Join(s[1:], " ") go u.BotReply(E64(in)) } case "d64": if len(s) >= 2 { in := strings.Join(s[1:], " ") go u.BotReply(D64(in)) } case "/trans": if update.Message.ReplyToMessage != nil && update.Message.ReplyToMessage.Text != "" { go u.BotReply(BaiduTranslate(baiduAPI, update.Message.ReplyToMessage.Text)) } else if len(s) >= 2 { in := strings.Join(s[1:], " ") go u.BotReply(BaiduTranslate(baiduAPI, in)) } case "/setman": if len(s) >= 3 { value := strings.Join(s[2:], " ") go u.SetMan(s[1], value) } case "/rmman": if len(s) >= 2 { go u.RmMan(s[1:]...) } case "/man": if len(s) == 1 { go u.ListMan() } else { go u.Man(s[1]) } case "/broadcast": if len(s) == 1 { go u.PreBroadcast() } else if len(s) >= 2 { msg := strings.Join(s[1:], " ") go u.Broadcast(msg) } default: if update.Message.Chat.ID > 0 { switch u.GetStatus() { case "auth": go u.Auth(update.Message.Text) case "broadcast": go u.Broadcast(update.Message.Text) default: if categoriesSet.Has(update.Message.Text) { // custom keyboard reply go u.BotReply(YamlList2String(conf, update.Message.Text)) } } } } } } }
// StoreItem stores an item into the library. func (library *Library) StoreItem(item interface{}, itemType int) error { var itemStruct *Item switch itemType { case LibraryItemSourceGroup, LibraryItemMetricGroup: itemStruct = item.(*Group).GetItem() case LibraryItemScale: itemStruct = item.(*Scale).GetItem() case LibraryItemUnit: itemStruct = item.(*Unit).GetItem() case LibraryItemGraph: itemStruct = item.(*Graph).GetItem() case LibraryItemCollection: itemStruct = item.(*Collection).GetItem() default: return os.ErrInvalid } // If item has no ID specified, generate one if itemStruct.ID == "" { uuidTemp, err := uuid.NewV4() if err != nil { return err } itemStruct.ID = uuidTemp.String() } else if !library.ItemExists(itemStruct.ID, itemType) { return os.ErrNotExist } // Check for name field presence/duplicates if itemStruct.Name == "" { logger.Log(logger.LevelError, "library", "item missing `name' field") return os.ErrInvalid } itemTemp, err := library.GetItemByName(itemStruct.Name, itemType) // Item exists, check for duplicates if err == nil { switch itemType { case LibraryItemSourceGroup, LibraryItemMetricGroup: if itemTemp.(*Group).ID != itemStruct.ID { logger.Log(logger.LevelError, "library", "duplicate group identifier `%s'", itemStruct.ID) return os.ErrExist } case LibraryItemScale: if itemTemp.(*Scale).ID != itemStruct.ID { logger.Log(logger.LevelError, "library", "duplicate scale identifier `%s'", itemStruct.ID) return os.ErrExist } case LibraryItemUnit: if itemTemp.(*Unit).ID != itemStruct.ID { logger.Log(logger.LevelError, "library", "duplicate unit identifier `%s'", itemStruct.ID) return os.ErrExist } case LibraryItemGraph: if itemTemp.(*Graph).ID != itemStruct.ID { logger.Log(logger.LevelError, "library", "duplicate graph identifier `%s'", itemStruct.ID) return os.ErrExist } case LibraryItemCollection: if itemTemp.(*Collection).ID != itemStruct.ID { logger.Log(logger.LevelError, "library", "duplicate collection identifier `%s'", itemStruct.ID) return os.ErrExist } } } // Item does not exist, store it into library switch itemType { case LibraryItemSourceGroup, LibraryItemMetricGroup: library.Groups[itemStruct.ID] = item.(*Group) library.Groups[itemStruct.ID].ID = itemStruct.ID case LibraryItemScale: library.Scales[itemStruct.ID] = item.(*Scale) library.Scales[itemStruct.ID].ID = itemStruct.ID case LibraryItemUnit: library.Units[itemStruct.ID] = item.(*Unit) library.Units[itemStruct.ID].ID = itemStruct.ID case LibraryItemGraph: // Check for definition names duplicates groupSet := set.New(set.ThreadSafe) seriesSet := set.New(set.ThreadSafe) for _, group := range item.(*Graph).Groups { if group == nil { logger.Log(logger.LevelError, "library", "found null group") return os.ErrInvalid } else if groupSet.Has(group.Name) { logger.Log(logger.LevelError, "library", "duplicate group name `%s'", group.Name) return os.ErrExist } groupSet.Add(group.Name) for _, series := range group.Series { if series == nil { logger.Log(logger.LevelError, "library", "found null series in group `%s'", group.Name) return os.ErrInvalid } else if seriesSet.Has(series.Name) { logger.Log(logger.LevelError, "library", "duplicate series name `%s'", series.Name) return os.ErrExist } seriesSet.Add(series.Name) } } library.Graphs[itemStruct.ID] = item.(*Graph) library.Graphs[itemStruct.ID].ID = itemStruct.ID case LibraryItemCollection: library.Collections[itemStruct.ID] = item.(*Collection) library.Collections[itemStruct.ID].ID = itemStruct.ID } itemStruct.Modified = time.Now() // Store JSON data if err := utils.JSONDump(library.getFilePath(itemStruct.ID, itemType), item, itemStruct.Modified); err != nil { return err } return nil }