Example #1
0
func getCaches(u utils.Utils, caches *sliceCache) error {
	if caches == nil || len(*caches) < 1 {
		return nil
	}

	items := make([]utils.MemoryItem, len(*caches))

	for index, cache := range *caches {
		items[index] = utils.MemoryItem{Key: getCacheKey(cache)}
	}

	if err := u.MemoryGet(&items); err != nil {
		u.Errorf("u.MemoryGet(%d) error %v", len(items), err)
		return err
	}

	for index, item := range items {
		parts := strings.Split(item.Value, ";")

		if count, err := strconv.ParseInt(parts[0], 10, 64); err == nil {
			(*caches)[index].Count = count
		}

		if len(parts) >= 2 {
			// value with expire timestamp
			if exp, expErr := strconv.ParseInt(parts[1], 10, 64); expErr == nil {
				(*caches)[index].TtlLeft = exp - time.Now().Unix()
			}
		}

		utils.Verbosef(u, "services.getCaches caches[%d] = %v", index, &(*caches)[index])
	}

	return nil
}
Example #2
0
func setCaches(u utils.Utils, caches *sliceCache) {
	if caches == nil || len(*caches) < 1 {
		return
	}

	items := make([]utils.MemoryItem, len(*caches))
	ttlMemory := utils.ConfigGetIntWithDefault(u, "TTL_MEMORY", 86400)
	ttlDefault := utils.ConfigGetTtlDefault(u)
	ttlRestricted := utils.ConfigGetIntWithDefault(u, "TTL_RESTRICTED", 60)

	for index, cache := range *caches {
		valueTtl := ttlDefault
		if cache.Count < 1 {
			valueTtl = ttlRestricted
		}

		items[index] = utils.MemoryItem{
			Key:   getCacheKey(cache),
			Value: fmt.Sprintf("%d;%d", cache.Count, time.Now().Unix()+valueTtl),
			Ttl:   ttlMemory,
		}
	}

	if err := u.MemorySet(&items); err != nil {
		u.Errorf("u.MemorySet(%d) error %v", len(items), err)
	}
}
Example #3
0
func getAdsAsJson(u utils.Utils) string {
	json, err := json.Marshal(u.ConfigGet("ADS"))
	if err != nil {
		return "''"
	}

	return string(json)
}
Example #4
0
func DataJson(u utils.Utils, w http.ResponseWriter, r *http.Request, oneUrl bool) {
	_, countsJson, err := getCountsJson(u, r, oneUrl)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		u.Errorf("web.DataJson: getCountsJson error %v", err)
		return
	}

	writeJson(u, w, r, countsJson)
}
func prepareFbGraphUrl(u utils.Utils, ids string) string {
	scheme := "http"
	accessToken := ""
	if appId := u.ConfigGet("FACEBOOK_APP_ID"); appId != "" {
		if appSecret := u.ConfigGet("FACEBOOK_APP_SECRET"); appSecret != "" {
			scheme = "https"
			accessToken = fmt.Sprintf("&access_token=%s|%s", appId, appSecret)
		}
	}

	return fmt.Sprintf("%s://graph.facebook.com/?ids=%s&fields=share%s", scheme, neturl.QueryEscape(ids), accessToken)
}
Example #6
0
func scheduleRefreshIfNeeded(u utils.Utils) {
	if dataNeedRefresh == nil {
		return
	}

	if dataNeedRefreshCount < utils.ConfigGetIntWithDefault(u, "REFRESH_BATCH_SIZE", 20) {
		return
	}

	u.Delay(DELAY_HANDLER_NAME_REFRESH, *dataNeedRefresh)
	dataNeedRefresh = nil
	dataNeedRefreshCount = 0
}
Example #7
0
func googleLegacy(u utils.Utils, url string) result {
	start := time.Now()
	var res result

	urlJson, err := json.Marshal(url)
	if err != nil {
		res.Error = err
		return res
	}

	// http://bradsknutson.com/blog/get-google-share-count-url/
	body := `[{"method":"pos.plusones.get","id":"p","params":{"nolog":true,"id":` + string(urlJson) + `,"source":"widget","userId":"@viewer","groupId":"@self"},"jsonrpc":"2.0","key":"p","apiVersion":"v1"}]`
	req, err := http.NewRequest("POST", "https://clients6.google.com/rpc", bytes.NewBufferString(body))
	if err != nil {
		res.Error = err
		return res
	}

	utils.Verbosef(u, "Calling http.Client.Do(body=%s)", body)
	req.Header.Set("Content-Type", "application/json")
	resp, err := u.HttpClient().Do(req)
	if err != nil {
		res.Error = err
		return res
	}

	defer resp.Body.Close()
	respBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		res.Error = err
		return res
	}
	res.Response = respBody
	u.Debugf("googleLegacy(url=%s) took %s", url, time.Since(start))

	jsonparser.ArrayEach(respBody, func(element []byte, _ jsonparser.ValueType, _ int, err error) {
		if err != nil {
			res.Error = err
			return
		}

		if count, err := jsonparser.GetFloat(element, "result", "metadata", "globalCounts", "count"); err != nil {
			res.Error = err
			return
		} else {
			res.Count = int64(count)
		}
	})

	return res
}
Example #8
0
func JqueryPluginJs(u utils.Utils, w http.ResponseWriter, r *http.Request) {
	jsData, err := ioutil.ReadFile("private/js/jquery.plugin.js")
	if err != nil {
		w.WriteHeader(http.StatusNotFound)
		u.Errorf("web.JqueryPluginJs: ReadFile error %v", err)
		return
	}

	jsonUrl := fmt.Sprintf("//%s/js/data.json", r.Host)
	js := strings.Replace(string(jsData), "{jsonUrl}", jsonUrl, 1)
	js = strings.Replace(js, "{ads}", getAdsAsJson(u), 1)

	writeJs(u, w, r, js)
}
Example #9
0
func getBlacklist(u utils.Utils, refresh bool) *regexp.Regexp {
	if !blacklistPrepared || refresh {
		if value := u.ConfigGet("BLACKLIST"); value != "" {
			compiled, err := regexp.Compile(value)
			if err != nil {
				u.Errorf("web.getBlacklist error on %s: %v", value, err)
			}

			blacklist = compiled
		}

		blacklistPrepared = true
	}

	return blacklist
}
Example #10
0
func getWhitelist(u utils.Utils, refresh bool) *regexp.Regexp {
	if !whitelistPrepared || refresh {
		if value := u.ConfigGet("WHITELIST"); value != "" {
			compiled, err := regexp.Compile(value)
			if err != nil {
				u.Errorf("web.getWhitelist error on %s: %v", value, err)
			}

			whitelist = compiled
		}

		whitelistPrepared = true
	}

	return whitelist
}
Example #11
0
func buildRequests(u utils.Utils, data *MapUrlServiceCount, handleNoValueOnly bool) MapServiceRequest {
	utils.Verbosef(u, "services.buildRequests(%s, %s)", data, handleNoValueOnly)

	requests := make(MapServiceRequest)
	caches := make(sliceCache, 0)

	for url, services := range *data {
		for service, count := range services {
			if handleNoValueOnly && count != COUNT_NO_VALUE {
				continue
			}

			worker, ok := workers[service]
			if !ok {
				u.Errorf("services.buildRequests: Unrecognized service %s", service)
				continue
			}

			// temporary mark the cached count as fresh to avoid other process
			// also trying to refresh it, we will take care of it later
			temporaryCount := count
			if temporaryCount == COUNT_NO_VALUE {
				temporaryCount = COUNT_INITIAL_VALUE
			}
			caches = append(caches, cache{Service: service, Url: url, Count: temporaryCount})

			if req, ok := requests[service]; ok {
				req.Urls = append(req.Urls, url)
				requests[service] = req
			} else {
				var newReq request
				newReq.Service = service
				newReq.Worker = worker
				newReq.Urls = []string{url}
				newReq.Results = make(MapUrlResult)

				requests[service] = newReq
			}
		}
	}

	setCaches(u, &caches)

	return requests
}
Example #12
0
func facebookWorker(u utils.Utils, req *request) {
	start := time.Now()
	urls := strings.Join(req.Urls, ",")
	url := prepareFbGraphUrl(u, urls)
	utils.Verbosef(u, "Calling http.Client.Get(%s)", url)

	resp, err := u.HttpClient().Get(url)
	if err != nil {
		req.Error = err
		return
	}

	defer resp.Body.Close()
	respBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		req.Error = err
		return
	}
	req.Response = respBody
	u.Debugf("facebookWorker(urls=%s) took %s", urls, time.Since(start))

	for _, url := range req.Urls {
		var res result

		if respUrl, _, _, err := jsonparser.Get(respBody, url); err != nil {
			res.Error = err
			res.Response = respBody
		} else {
			res.Response = respUrl
			if shareCount, err := jsonparser.GetInt(respUrl, "share", "share_count"); err != nil {
				// it's alright, for new urls Facebook does not return share.share_count at all
				res.Count = COUNT_INITIAL_VALUE
			} else {
				res.Count = shareCount
			}
		}

		req.Results[url] = res
	}

	return
}
Example #13
0
func getCountsJson(u utils.Utils, r *http.Request, oneUrl bool) (string, string, error) {
	requestedUrls := parseUrls(r)
	requestedServices := parseServices(r)
	data := services.DataSetup()

	if len(requestedUrls) < 1 {
		return "", "{}", nil
	}

	url := ""
	if oneUrl {
		url = requestedUrls[0]
		requestedUrls = []string{url}
	}

	for _, requestedUrl := range requestedUrls {
		if !RulesAllowUrl(u, requestedUrl) {
			u.Errorf("Url not allowed %s", requestedUrl)
			continue
		}

		for _, requestedService := range requestedServices {
			services.DataAdd(&data, requestedService, requestedUrl)
		}
	}

	services.FillData(u, &data)

	var dataByte []byte
	var dataErr error
	if oneUrl {
		dataByte, dataErr = json.Marshal(data[url])
	} else {
		dataByte, dataErr = json.Marshal(data)
	}
	if dataErr != nil {
		return url, "{}", dataErr
	}

	return url, string(dataByte), nil
}
Example #14
0
func ConfigPost(u utils.Utils, w http.ResponseWriter, r *http.Request) {
	specifiedSecret := parseSecret(r)
	configSecret := os.Getenv("CONFIG_SECRET")
	if configSecret == "" || specifiedSecret != configSecret {
		w.WriteHeader(http.StatusForbidden)
		u.Errorf("admin.ConfigGet: wrong secret %s", specifiedSecret)
		return
	}

	r.ParseForm()
	if keys, ok := r.PostForm["key"]; ok {
		for _, key := range keys {
			if len(key) < 1 {
				continue
			}

			if values, ok := r.PostForm[key]; ok {
				for _, value := range values {
					if err := u.ConfigSet(key, value); err != nil {
						w.WriteHeader(http.StatusInternalServerError)
						u.Errorf("admin.ConfigSet: u.ConfigSet(%q, %q) error %v", key, value, err)
						return
					}
				}
			}
		}
	}

	RulesRefresh(u)
	w.WriteHeader(http.StatusAccepted)
}
Example #15
0
func ConfigGet(u utils.Utils, w http.ResponseWriter, r *http.Request) {
	specifiedSecret := parseSecret(r)
	configSecret := os.Getenv("CONFIG_SECRET")
	if configSecret == "" || specifiedSecret != configSecret {
		w.WriteHeader(http.StatusForbidden)
		writeJson(u, w, r, "{}")
		u.Errorf("admin.ConfigGet: wrong secret %s", specifiedSecret)
		return
	}

	keys := parseKeys(r)
	values := make(map[string]string)
	for _, key := range keys {
		values[key] = u.ConfigGet(key)
	}

	valuesJson, err := json.Marshal(values)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		writeJson(u, w, r, "{}")
		u.Errorf("admin.ConfigGet: json.Marshal(values) error %v", err)
		return
	}

	writeJson(u, w, r, string(valuesJson))
}
Example #16
0
func fillDataFromCache(u utils.Utils, data *MapUrlServiceCount, handleNoValueOnly bool) {
	caches := make(sliceCache, 0)

	for url, services := range *data {
		for service, count := range services {
			if handleNoValueOnly && count != COUNT_NO_VALUE {
				continue
			}

			caches = append(caches, cache{Service: service, Url: url, Count: COUNT_NO_VALUE})
		}
	}

	if err := getCaches(u, &caches); err != nil {
		u.Errorf("services.getCaches(%d) error %v", len(caches), err)
	} else {
		for _, cache := range caches {
			(*data)[cache.Url][cache.Service] = cache.Count
		}

		checkCachesForRefresh(u, &caches)
	}
}
Example #17
0
func twitterLegacy(u utils.Utils, url string) result {
	var res result
	start := time.Now()
	oscUrl := "http://opensharecount.com/count.json?url=" + neturl.QueryEscape(url)
	utils.Verbosef(u, "Calling http.Client.Get(%s)", oscUrl)

	resp, err := u.HttpClient().Get(oscUrl)
	if err != nil {
		res.Error = err
		return res
	}

	defer resp.Body.Close()
	respBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		res.Error = err
		return res
	}
	res.Response = respBody
	u.Debugf("twitterLegacy(url=%s) took %s", url, time.Since(start))

	if count, err := jsonparser.GetInt(respBody, "count"); err != nil {
		res.Error = err
		return res
	} else {
		if count == 0 {
			if oscError, err := jsonparser.GetString(respBody, "error"); err != nil {
				res.Error = errors.New(oscError)
				return res
			}
		}

		res.Count = count
	}

	return res
}
Example #18
0
func AllJs(u utils.Utils, w http.ResponseWriter, r *http.Request) {
	url, countsJson, err := getCountsJson(u, r, true)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		u.Errorf("web.AllJs: getCountsJson error %v", err)
		return
	}

	urlByte, err := json.Marshal(url)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		u.Errorf("web.AllJs: json.Marshal(url) error %v", err)
		return
	}

	jsData, err := ioutil.ReadFile("private/js/all.js")
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		u.Errorf("web.AllJs: ReadFile error %v", err)
		return
	}
	js := string(jsData)
	js = strings.Replace(js, "{url}", string(urlByte), 1)
	js = strings.Replace(js, "{now}", fmt.Sprintf("%v", time.Now()), 1)

	// keep using css.MinifyFromFile because it does the data uri inline for us
	// TODO: drop this github.com/daohoangson/go-minify/css dependency
	css := css.MinifyFromFile("public/css/main.css")
	css = MinifyCss(css)
	js = strings.Replace(js, "{css}", css, 1)

	js = strings.Replace(js, "{facebooksvg}", readSvgAsJson("private/img/facebook.svg"), 1)
	js = strings.Replace(js, "{twittersvg}", readSvgAsJson("private/img/twitter.svg"), 1)
	js = strings.Replace(js, "{googlesvg}", readSvgAsJson("private/img/google.svg"), 1)

	js = strings.Replace(js, "{ads}", getAdsAsJson(u), 1)
	js = strings.Replace(js, "{counts}", string(countsJson), 1)
	js = strings.Replace(js, "{shorten}", parseShortenAsBool(r), 1)
	js = strings.Replace(js, "{target}", parseTargetAsJson(r), 1)

	writeJs(u, w, r, js)
}
Example #19
0
func HistoryJson(u utils.Utils, w http.ResponseWriter, r *http.Request) {
	requestedUrls := parseUrls(r)
	url := requestedUrls[0]

	records, err := u.HistoryLoad(url)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		u.Errorf("web.HistoryJson: HistoryLoad error %v", err)
		return
	}

	data := make(map[string]HistorySlot)
	slotSize := int64(300) // each slot lasts 5 minutes
	for _, record := range records {
		slotInt64 := record.Time.Unix() / slotSize * slotSize
		slotString := fmt.Sprintf("%d", slotInt64)

		if slot, ok := data[slotString]; ok {
			if _, ok := slot.Counts[record.Service]; !ok {
				slot.Counts[record.Service] = record.Count
				slot.Total += record.Count
				data[slotString] = slot
			}
		} else {
			data[slotString] = HistorySlot{
				Time:   time.Unix(slotInt64, 0).Format(time.RFC1123),
				Counts: map[string]int64{record.Service: record.Count},
				Total:  record.Count,
			}
		}
	}

	historyJson, err := json.Marshal(data)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		u.Errorf("web.HistoryJson: json.Marshal error %v", err)
		return
	}

	writeJson(u, w, r, string(historyJson))
}
Example #20
0
func RulesAllowUrl(u utils.Utils, url string) bool {
	if !getBasic().MatchString(url) {
		u.Debugf("web.RulesAllowUrl: %s is not a valid url", url)
		return false
	}

	if wl := getWhitelist(u, false); wl != nil {
		if !wl.MatchString(url) {
			u.Debugf("web.RulesAllowUrl: %s is not whitelisted", url)
			return false
		}
	}

	if bl := getBlacklist(u, false); bl != nil {
		if bl.MatchString(url) {
			u.Debugf("web.RulesAllowUrl: %s is blacklisted", url)
			return false
		}
	}

	return true
}
Example #21
0
func executeRequests(u utils.Utils, requests *MapServiceRequest, data *MapUrlServiceCount) {
	utils.Verbosef(u, "services.executeRequests(%s)", requests)
	if len(*requests) < 1 {
		return
	}

	var wg sync.WaitGroup
	var cacheWg sync.WaitGroup
	cacheCh := make(chan cache, 1)
	caches := make(sliceCache, 0)
	var historyWg sync.WaitGroup
	historyTime := time.Now()
	historyCh := make(chan utils.HistoryRecord, 1)
	histories := make([]utils.HistoryRecord, 0)

	wg.Add(len(*requests))
	for _, req := range *requests {
		go func(req request) {
			defer wg.Done()

			req.Worker(u, &req)
			if req.Error != nil {
				u.Errorf("services.%s: %v", req.Service, req.Error)
			}

			for url, res := range req.Results {
				oldCount, _ := (*data)[url][req.Service]
				(*data)[url][req.Service] = res.Count

				if res.Error != nil {
					u.Errorf("services.%s: %s error %v response %s", req.Service, url, res.Error, res.Response)
				} else {
					if res.Count > COUNT_INITIAL_VALUE && res.Count > oldCount {
						cacheWg.Add(1)
						cacheCh <- cache{Service: req.Service, Url: url, Count: res.Count}

						historyWg.Add(1)
						historyCh <- utils.HistoryRecord{Service: req.Service, Url: url, Count: res.Count, Time: historyTime}
					}
				}
			}
		}(req)
	}

	go func() {
		for cache := range cacheCh {
			caches = append(caches, cache)
			cacheWg.Done()
		}
	}()

	go func() {
		for history := range historyCh {
			histories = append(histories, history)
			historyWg.Done()
		}
	}()

	wg.Wait()
	cacheWg.Wait()
	historyWg.Wait()

	setCaches(u, &caches)
	if err := u.HistorySave(&histories); err != nil {
		u.Errorf("u.HistorySave error %v", err)
	}
}
Example #22
0
func RulesRefresh(u utils.Utils) {
	getWhitelist(u, true)
	getBlacklist(u, true)

	u.Debugf("web.RulesReset ok")
}