Example #1
0
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,
	}
}
Example #2
0
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)
}
Example #3
0
// 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
}
Example #4
0
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]})
			}
		}
	}
}
Example #5
0
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)
}
Example #6
0
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)
}
Example #8
0
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)
}
Example #9
0
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)
}
Example #10
0
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
}
Example #11
0
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
}
Example #12
0
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
}
Example #13
0
// 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)
	}
}
Example #14
0
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)
			}
		}
	}
}
Example #15
0
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)
}
Example #16
0
// 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
}
Example #17
0
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)
}
Example #18
0
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()
}
Example #19
0
// 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
}
Example #20
0
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)
}
Example #24
0
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
}
Example #25
0
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)
}
Example #26
0
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))
						}
					}
				}
			}
		}
	}
}
Example #27
0
// 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
}