src

package
v0.0.0-...-d2e14b6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 6, 2024 License: MIT Imports: 22 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var CONSTANT = constant{
	HISTORY_DB:       "_history.db",
	FAVICON_DB:       "_favicon.db",
	MEDIA_HISTORY_DB: "_mediaHistory.db",
	WEB_DATA_DB:      "_webData.db",
	LOGIN_DATA_DB:    "_loginData.db",
	COOKIE_DB:        "_cookies.db",
}
View Source
var CacheFavicons = func(wf *aw.Workflow) {
	historyDB := GetHistoryDB(wf)
	GetFaviconDB(wf)
	faviconDBFilePath := filepath.Join(GetTempDataPath(wf), CONSTANT.FAVICON_DB)

	attachStmt, err := historyDB.Prepare(fmt.Sprintf(`ATTACH DATABASE '%s' AS favicons`, faviconDBFilePath))
	attachStmt.Exec()

	dbQuery := `
		SELECT urls.url, favicon_bitmaps.image_data, favicon_bitmaps.last_updated
			FROM urls
				LEFT OUTER JOIN icon_mapping ON icon_mapping.page_url = urls.url,
					favicon_bitmaps ON favicon_bitmaps.id =
						(SELECT id FROM favicon_bitmaps
							WHERE favicon_bitmaps.icon_id = icon_mapping.icon_id
							ORDER BY width DESC LIMIT 1)
			WHERE (urls.title LIKE '%%' OR urls.url LIKE '%%')
		`

	rows, err := historyDB.Query(dbQuery)
	CheckError(err)

	var url string
	var faviconBitmapData string
	var faviconLastUpdated string

	for rows.Next() {
		err := rows.Scan(&url, &faviconBitmapData, &faviconLastUpdated)
		CheckError(err)

		domainName := ExtractDomainName(url)
		iconPath := fmt.Sprintf(`%s/%s.png`, GetFaviconDirectoryPath(wf), domainName)

		if !FileExist(iconPath) {
			ioutil.WriteFile(iconPath, []byte(faviconBitmapData), os.FileMode(0777))
		}
	}

	currenttime := time.Now().Local()
	err = os.Chtimes(GetFaviconDirectoryPath(wf), currenttime, currenttime)
	CheckError(err)

	fmt.Println(" ")
}
View Source
var ChangeBrowser = func(browserName string) {
	err := ConfigAPI.Set("BROWSER", browserName, true).Do()
	CheckError(err)

	CopyFile(fmt.Sprintf("assets/browser-icons/%s.png", browserName), "icon.png")

	fmt.Print(browserName)
}
View Source
var ChangeProfile = func(profileName string) {

	if !FileExist(GetProfileRootPath(Conf.Browser)) {
		fmt.Print("")
		return
	}

	err := ConfigAPI.Set("PROFILE", profileName, true).Do()
	CheckError(err)
	fmt.Print(profileName)
}
View Source
var CheckBrowserIsInstalled = func(browserName string) bool {
	return FileExist(GetProfileRootPath(browserName))
}
View Source
var CheckError = func(err error) {
	if err != nil {
		panic(err)
	}
}
View Source
var CloseTab = func(query string) {
	argv := strings.Split(query, ",")
	_, err := util.RunJS(getCloseTabScript(), argv...)
	CheckError(err)
}
View Source
var Conf = &WorkflowConfig{}
View Source
var ConfigAPI *aw.Config
View Source
var ConvertChromeTimeToUnixTimestamp = func(time int64) int64 {
	return int64((math.Floor((float64(time) / 1000000) - 11644473600)))
}
View Source
var EnsureFaviconCacheUptodated = func(wf *aw.Workflow) {
	faviconCacheDir := GetFaviconDirectoryPath(wf)

	if isEmpty, err := IsEmptyDirectory(faviconCacheDir); isEmpty || err != nil {
		defer func() {
			err := recover()
			log.Println("Error occurs in caching favicon: ", err)
		}()

		CacheFavicons(wf)
	} else if IsFaviconCacheExpired(wf) {
		cmd := exec.Command(os.Args[0], "cache-favicons")
		wf.RunInBackground("favicon-cache", cmd)
	}
}
View Source
var ExtractDomainName = func(url string) (domainName string) {
	if !isValidUrl(url) {
		return "unknown"
	}

	var hostname string
	if strings.Contains(url, "//") {
		hostname = strings.Split(url, "/")[2]
	} else {
		hostname = strings.Split(url, "/")[0]
	}

	hostname = strings.Split(hostname, ":")[0]
	hostname = strings.Split(hostname, "?")[0]

	domainName, err := psl.Domain(hostname)
	if err != nil {
		return hostname
	}

	return domainName
}
View Source
var FetchAutofillData = func(wf *aw.Workflow, query string) {
	var dbQuery = fmt.Sprintf(`
		SELECT value, name, date_created, count
			FROM autofill
			WHERE value LIKE '%%%s%%' OR name LIKE '%%%s%%'
			ORDER BY count DESC
	`, query, query)

	webDataDB := GetWebDataDB(wf)
	rows, err := webDataDB.Query(dbQuery)
	CheckError(err)

	var autofillValue string
	var autofillLabel string
	var createdDate int64
	var count int

	for rows.Next() {
		err := rows.Scan(&autofillValue, &autofillLabel, &createdDate, &count)
		CheckError(err)

		var subtitle string

		unixTimestamp := ConvertChromeTimeToUnixTimestamp(createdDate)
		localeTimeStr := GetLocaleString(unixTimestamp)

		subtitle += fmt.Sprintf(`Label: '%s', Created in '%s'`, autofillLabel, localeTimeStr)

		item := wf.NewItem(autofillValue).
			Subtitle(subtitle).
			Valid(true).
			Copytext(autofillValue).
			Arg(autofillValue).
			Largetype(autofillValue).
			Autocomplete(autofillValue).
			Icon(&aw.Icon{"assets/info.png", ""})

		item.Cmd().Subtitle("Press Enter to paste this value directly")
	}
}
View Source
var FetchBookmark = func(wf *aw.Workflow, query string) {
	InitBookmarkJsonTraversal()
	bookmarkRoot := GetChromeBookmark()
	input, flags := ParseQueryFlags(query)
	var bookmarks []BookmarkItem

	if folderId, ok := flags["folderId"]; ok {
		folders := TraverseBookmarkJSONObject(bookmarkRoot, TraverseBookmarkJsonOption{Targets: []string{"folder"}, Depth: 99})

		for _, folder := range folders {
			if folder.Id == folderId {
				bookmarks = TraverseBookmarkArray(folder.Children, TraverseBookmarkJsonOption{Targets: []string{"url"}, Depth: 1})
			}
		}
		if bookmarks == nil {
			panic(fmt.Sprintf("folderId not found: %s", folderId))
		}
	} else {
		bookmarks = TraverseBookmarkJSONObject(bookmarkRoot, TraverseBookmarkJsonOption{Targets: []string{"url"}, Depth: 99})
	}

	historyDB := GetHistoryDB(wf)
	visitHistories, err := historyDB.Query("SELECT url FROM urls")
	CheckError(err)

	visitFrequency := make(map[string]int)

	for visitHistories.Next() {
		var url string
		err := visitHistories.Scan(&url)
		CheckError(err)

		visitFrequency[url] += 1
	}

	sort.Slice(bookmarks, func(i, j int) bool {
		ithFreq := visitFrequency[bookmarks[i].Url]
		jthFreq := visitFrequency[bookmarks[j].Url]

		if ithFreq > 0 && jthFreq > 0 {
			if ithFreq > jthFreq {
				return true
			} else {
				return false
			}
		}

		if ithFreq > 0 {
			return true
		}

		return false
	})

	for _, bookmark := range bookmarks {
		domainName := ExtractDomainName(bookmark.Url)
		iconPath := fmt.Sprintf(`%s/%s.png`, GetFaviconDirectoryPath(wf), domainName)
		CheckError(err)

		item := wf.NewItem(bookmark.Name).
			Valid(true).
			Subtitle(bookmark.Url).
			Quicklook(bookmark.Url).
			Arg(bookmark.Url).
			Copytext(bookmark.Url).
			Autocomplete(bookmark.Name).
			Largetype(bookmark.Name)

		item.Cmd().Subtitle("Press Enter to copy this url to clipboard")

		if FileExist(iconPath) {
			item.Icon(&aw.Icon{iconPath, ""})
		}
	}

	if input != "" {
		wf.Filter(input)
	}
}
View Source
var FetchBookmarkFolder = func(wf *aw.Workflow, query string) {
	InitBookmarkJsonTraversal()
	bookmarkRoot := GetChromeBookmark()

	bookmarkFolders := TraverseBookmarkJSONObject(bookmarkRoot, TraverseBookmarkJsonOption{Targets: []string{"folder"}, Depth: 99})
	sort.Slice(bookmarkFolders, func(i, j int) bool {
		if strings.Compare(bookmarkFolders[i].Name, bookmarkFolders[j].Name) == 1 {
			return true
		} else {
			return false
		}
	})

	for _, folder := range bookmarkFolders {
		folderChildLen := 0
		if folder.Children != nil {
			for _, child := range folder.Children {
				if child.(map[string]interface{})["type"] == "url" {
					folderChildLen += 1
				}
			}
		}

		wf.NewItem(folder.Name).
			Valid(true).
			Subtitle(fmt.Sprintf(`%d items included`, folderChildLen)).
			Arg(folder.Id).
			Autocomplete(folder.Name).
			Copytext(folder.Name).
			Largetype(folder.Name).
			Icon(&aw.Icon{"assets/folder.png", ""}).
			Var("folder", fmt.Sprintf(`--%s=%s`, "folderId", folder.Id))
	}

	if query != "" {
		wf.Filter(query)
	}
}
View Source
var FetchDownloadHistory = func(wf *aw.Workflow, query string, showOnlyExistingFiles bool) {
	var dbQuery = `SELECT current_path, referrer, total_bytes, start_time FROM downloads ORDER BY start_time DESC`

	historyDB := GetHistoryDB(wf)
	rows, err := historyDB.Query(dbQuery)
	CheckError(err)

	var downloadedFilePath string
	var downloadedFileFrom string
	var downloadedFileBytes int
	var downloadedStartTime int64

	for rows.Next() {
		err := rows.Scan(&downloadedFilePath, &downloadedFileFrom, &downloadedFileBytes, &downloadedStartTime)
		CheckError(err)

		fileNameArr := strings.Split(downloadedFilePath, "/")
		fileName := fileNameArr[len(fileNameArr)-1]
		if fileName == "" {
			continue
		}

		var subtitle string
		if FileExist(downloadedFilePath) {
			subtitle = "[✔] "
		} else {
			if showOnlyExistingFiles == true {
				continue
			}
			subtitle = "[✖] "
		}

		domainName := ExtractDomainName(downloadedFileFrom)
		unixTimestamp := ConvertChromeTimeToUnixTimestamp(downloadedStartTime)
		localeTimeStr := GetLocaleString(unixTimestamp)

		subtitle += localeTimeStr

		item := wf.NewItem(fileName).
			Subtitle(subtitle).
			Valid(true).
			Arg(downloadedFilePath).
			Quicklook(downloadedFilePath).
			Autocomplete(fileName).
			Copytext(downloadedFilePath).
			Largetype(downloadedFilePath)

		iconPath := fmt.Sprintf(`%s/%s.png`, GetFaviconDirectoryPath(wf), domainName)

		if FileExist(iconPath) {
			item.Icon(&aw.Icon{iconPath, ""})
		}
	}

	if query != "" {
		wf.Filter(query)
	}
}
View Source
var FetchHistory = func(wf *aw.Workflow, query string) {
	titleQuery, domainQuery, isDomainSearch := ParseUserQuery(query)

	var dbQuery = fmt.Sprintf(`
		SELECT urls.id, urls.title, urls.url, urls.last_visit_time FROM urls
		WHERE urls.title LIKE '%%%s%%'
		ORDER BY last_visit_time DESC
	`, titleQuery)

	historyDB := GetHistoryDB(wf)

	rows, err := historyDB.Query(dbQuery)
	CheckError(err)

	var urlTitle string
	var url string
	var urlId string
	var urlLastVisitTime int64

	var itemCount = 0
	var previousTitle = ""

	for rows.Next() {
		if itemCount >= Conf.ResultCountLimit {
			break
		}

		err := rows.Scan(&urlId, &urlTitle, &url, &urlLastVisitTime)
		CheckError(err)

		if previousTitle == urlTitle {
			continue
		}

		domainName := ExtractDomainName(url)
		if isDomainSearch && !strings.Contains(domainName, domainQuery) {
			continue
		}

		unixTimestamp := ConvertChromeTimeToUnixTimestamp(urlLastVisitTime)
		localeTimeStr := GetLocaleString(unixTimestamp)

		item := wf.NewItem(urlTitle).
			Subtitle(localeTimeStr).
			Valid(true).
			Quicklook(url).
			Autocomplete(urlTitle).
			Arg(url).
			Copytext(url).
			Largetype(urlTitle)

		item.Cmd().Subtitle("Press Enter to copy this url to clipboard")

		iconPath := fmt.Sprintf(`%s/%s.png`, GetFaviconDirectoryPath(wf), domainName)

		if FileExist(iconPath) {
			item.Icon(&aw.Icon{iconPath, ""})
		}

		previousTitle = urlTitle
		itemCount += 1
	}
}
View Source
var FetchLoginData = func(wf *aw.Workflow, query string) {
	var dbQuery = fmt.Sprintf(`
		SELECT username_element, username_value, origin_url
			FROM logins
			WHERE origin_url LIKE '%%%s%%' OR username_element LIKE '%%%s%%' OR username_value LIKE '%%%s%%'
			ORDER BY date_last_used
	`, query, query, query)

	loginDataDB := GetLoginDataDB(wf)

	rows, err := loginDataDB.Query(dbQuery)
	CheckError(err)

	var userNameValue string
	var userNameElement string
	var originUrl string

	for rows.Next() {
		err := rows.Scan(&userNameElement, &userNameValue, &originUrl)
		CheckError(err)

		if userNameValue == "" {
			continue
		}

		domainName := ExtractDomainName(originUrl)
		iconPath := fmt.Sprintf(`%s/%s.png`, GetFaviconDirectoryPath(wf), domainName)

		var subtitle string
		if userNameElement != "" {
			subtitle = fmt.Sprintf(`Used in '%s', Group: %s`, userNameElement, domainName)
		} else {
			subtitle = fmt.Sprintf(`Used in '%s'`, domainName)
		}

		item := wf.NewItem(userNameValue).
			Subtitle(subtitle).
			Valid(true).
			Arg(userNameValue).
			Autocomplete(userNameValue).
			Copytext(userNameValue).
			Largetype(userNameValue)

		item.Cmd().Subtitle("Press Enter to paste this value directly")

		if FileExist(iconPath) {
			item.Icon(&aw.Icon{iconPath, ""})
		}
	}
}
View Source
var FetchSearchData = func(wf *aw.Workflow, query string) {
	titleQuery, domainQuery, isDomainSearch := ParseUserQuery(query)

	var dbQuery = fmt.Sprintf(`
		SELECT urls.url, urls.last_visit_time, keyword_search_terms.term
			FROM keyword_search_terms
			JOIN urls ON urls.id = keyword_search_terms.url_id
			WHERE keyword_search_terms.term LIKE '%%%s%%'
		ORDER BY last_visit_time DESC
	`, titleQuery)

	historyDB := GetHistoryDB(wf)

	rows, err := historyDB.Query(dbQuery)
	CheckError(err)

	var urlTitle string
	var url string
	var urlLastVisitTime int64

	var itemCount = 0
	var previousTitle = ""

	for rows.Next() {
		if itemCount >= Conf.ResultCountLimit {
			break
		}

		err := rows.Scan(&url, &urlLastVisitTime, &urlTitle)
		CheckError(err)

		if previousTitle == urlTitle {
			continue
		}

		domainName := ExtractDomainName(url)
		if isDomainSearch && !strings.Contains(domainName, domainQuery) {
			continue
		}

		unixTimestamp := ConvertChromeTimeToUnixTimestamp(urlLastVisitTime)
		localeTimeStr := GetLocaleString(unixTimestamp)

		item := wf.NewItem(urlTitle).
			Subtitle(localeTimeStr).
			Valid(true).
			Quicklook(url).
			Autocomplete(urlTitle).
			Arg(url).
			Copytext(url).
			Largetype(urlTitle)

		item.Cmd().Subtitle("Press Enter to copy this url to clipboard")

		iconPath := fmt.Sprintf(`%s/%s.png`, GetFaviconDirectoryPath(wf), domainName)

		if FileExist(iconPath) {
			item.Icon(&aw.Icon{iconPath, ""})
		}

		previousTitle = urlTitle
		itemCount += 1
	}
}
View Source
var FileExist = func(filepath string) bool {
	if _, err := os.Stat(filepath); errors.Is(err, os.ErrNotExist) {
		return false
	}
	return true
}
View Source
var FocusTab = func(query string) {
	argv := strings.Split(query, ",")
	_, err := util.RunJS(getFocusTabScript(), argv...)
	CheckError(err)
}
View Source
var GetChromeBookmark = func() map[string]interface{} {
	var bookmarkJson map[string]interface{}
	var bookmarkFilePath = GetDBFilePath(Conf.Browser, Conf.Profile, "Bookmarks")

	bookmarkData, err := ioutil.ReadFile(bookmarkFilePath)
	CheckError(err)
	err = json.Unmarshal(bookmarkData, &bookmarkJson)
	CheckError(err)

	return bookmarkJson["roots"].(map[string]interface{})
}
View Source
var GetDBFilePath = func(browserName string, chromeProfilePath string, dbFile string) string {
	if browserName == "Opera" {
		return fmt.Sprintf(`%s/%s`, GetProfileRootPath(browserName), dbFile)
	}
	return fmt.Sprintf(`%s/%s/%s`, GetProfileRootPath(browserName), chromeProfilePath, dbFile)
}
View Source
var GetFaviconDB = func(wf *aw.Workflow) *sql.DB {
	var targetPath = GetDBFilePath(Conf.Browser, Conf.Profile, "Favicons")
	dest := filepath.Join(GetTempDataPath(wf), CONSTANT.FAVICON_DB)
	CopyFile(targetPath, dest)
	db, err := sql.Open("sqlite3", dest)
	CheckError(err)

	return db
}
View Source
var GetFaviconDirectoryPath = func(wf *aw.Workflow) string {

	faviconCache := aw.NewCache(filepath.Join(wf.Cache.Dir, "favicon"))
	return faviconCache.Dir
}
View Source
var GetHistoryDB = func(wf *aw.Workflow) *sql.DB {
	var targetPath = GetDBFilePath(Conf.Browser, Conf.Profile, "History")
	dest := filepath.Join(GetTempDataPath(wf), CONSTANT.HISTORY_DB)
	CopyFile(targetPath, dest)
	db, err := sql.Open("sqlite3", dest)
	CheckError(err)

	return db
}
View Source
var GetLocaleString = func(unixTime int64) string {
	return lctime.Strftime("%c", time.Unix(unixTime, 0))
}
View Source
var GetLoginDataDB = func(wf *aw.Workflow) *sql.DB {
	var targetPath = GetDBFilePath(Conf.Browser, Conf.Profile, "Login Data")
	dest := filepath.Join(GetTempDataPath(wf), CONSTANT.WEB_DATA_DB)
	CopyFile(targetPath, dest)
	db, err := sql.Open("sqlite3", dest)
	CheckError(err)

	return db
}
View Source
var GetProfileRootPath = func(browserName string) string {
	var targetPath string

	user, err := user.Current()
	CheckError(err)
	userName := user.Username

	switch browserName {
	case "Opera":
		targetPath = `/Users/%s/Library/Application Support/com.operasoftware.Opera`
	case "Chrome Canary":
		targetPath = `/Users/%s/Library/Application Support/Google/Chrome Canary`
	case "Edge":
		targetPath = `/Users/%s/Library/Application Support/Microsoft Edge`
	case "Edge Canary":
		targetPath = `/Users/%s/Library/Application Support/Microsoft Edge Canary`
	case "Chromium":
		targetPath = `/Users/%s/Library/Application Support/Google/Chrome Cloud Enrollment`
	case "Brave":
		targetPath = `/Users/%s/Library/Application Support/BraveSoftware/Brave-Browser`
	case "Chrome":
		targetPath = `/Users/%s/Library/Application Support/Google/Chrome`
	case "Chrome Beta":
		targetPath = `/Users/%s/Library/Application Support/Google/Chrome Beta`
	case "Naver Whale":
		targetPath = `/Users/%s/Library/Application Support/Naver/Whale`
	case "Vivaldi":
		targetPath = `/Users/%s/Library/Application Support/Vivaldi`
	case "Epic":
		targetPath = `/Users/%s/Library/Application Support/HiddenReflex/Epic`
	case "Arc":
		targetPath = `/Users/%s/Library/Application Support/Arc/User Data`
	default:
		panic("Unsupported browser. Please consider to make a issue to support the browser if the browser is based on Chromium.")
	}

	return fmt.Sprintf(targetPath, userName)
}
View Source
var GetTempDataPath = func(wf *aw.Workflow) string {
	temp := aw.NewCache(filepath.Join(wf.Data.Dir, "temp"))
	return temp.Dir
}
View Source
var GetWebDataDB = func(wf *aw.Workflow) *sql.DB {
	var targetPath = GetDBFilePath(Conf.Browser, Conf.Profile, "Web Data")
	dest := filepath.Join(GetTempDataPath(wf), CONSTANT.WEB_DATA_DB)
	CopyFile(targetPath, dest)
	db, err := sql.Open("sqlite3", dest)
	CheckError(err)

	return db
}
View Source
var ImportConfig = func() {
	ConfigAPI = aw.NewConfig()

	if err := ConfigAPI.To(Conf); err != nil {
		panic(err)
	}
}
View Source
var InitBookmarkJsonTraversal = func() {
	TraverseBookmarkJSONObject = func(jsonObject map[string]interface{}, options TraverseBookmarkJsonOption) (result []BookmarkItem) {

		if options.Depth <= -1 {
			return []BookmarkItem{}
		}

		if jsonObject["type"] == "url" {
			if StringContains(options.Targets, "url") {
				return []BookmarkItem{
					{
						jsonObject["id"].(string),
						jsonObject["url"].(string),
						jsonObject["name"].(string),
						nil,
					},
				}
			}

			return []BookmarkItem{}
		}

		if StringContains(options.Targets, "folder") && jsonObject["type"] == "folder" {
			result = append(result, BookmarkItem{
				jsonObject["id"].(string),
				"",
				jsonObject["name"].(string),
				jsonObject["children"].([]interface{}),
			})

			childResult := TraverseBookmarkArray(jsonObject["children"].([]interface{}), options)
			result = append(result, childResult...)
			return result
		}

		target := jsonObject

		for _, child := range target {
			switch child.(type) {
			case map[string]interface{}:
				childResult := TraverseBookmarkJSONObject(child.(map[string]interface{}), options)
				result = append(result, childResult...)
			case []interface{}:
				childResult := TraverseBookmarkArray(child.([]interface{}), options)
				result = append(result, childResult...)
			}
		}

		return result
	}

	TraverseBookmarkArray = func(item []interface{}, options TraverseBookmarkJsonOption) []BookmarkItem {

		if options.Depth <= -1 {
			return []BookmarkItem{}
		}

		target := item
		result := []BookmarkItem{}

		for _, child := range target {
			switch child.(type) {
			case map[string]interface{}:
				childResult := TraverseBookmarkJSONObject(child.(map[string]interface{}), options)
				result = append(result, childResult...)
			case []interface{}:
				childResult := TraverseBookmarkArray(child.([]interface{}), options)
				result = append(result, childResult...)
			}
		}

		return result
	}
}
View Source
var IsFaviconCacheExpired = func(wf *aw.Workflow) bool {
	faviconCacheDir := GetFaviconDirectoryPath(wf)
	fileInfo, err := os.Stat(faviconCacheDir)
	CheckError(err)

	return time.Since(fileInfo.ModTime()) > time.Hour*24*3
}
View Source
var ListOpenedTabs = func(wf *aw.Workflow, query string) {
	query = strings.ToLower(query)
	stdout, err := util.RunJS(getListUpTabScript(), query)
	CheckError(err)

	var serializedStdout map[string]interface{}
	err = json.Unmarshal([]byte(stdout), &serializedStdout)
	CheckError(err)
	items := serializedStdout["items"].([]interface{})

	for _, item := range items {
		url := item.(map[string]interface{})["url"].(string)
		domainName := ExtractDomainName(url)
		item.(map[string]interface{})["domain"] = domainName

		iconPath := fmt.Sprintf(`%s/%s.png`, GetFaviconDirectoryPath(wf), domainName)
		if FileExist(iconPath) {
			item.(map[string]interface{})["icon"] = map[string]string{"path": iconPath}
		}
	}

	sort.Slice(items, func(i, j int) bool {
		ithDomainName := items[i].(map[string]interface{})["domain"].(string)
		jthDomainName := items[j].(map[string]interface{})["domain"].(string)

		return ithDomainName > jthDomainName
	})

	result, err := json.Marshal(serializedStdout)
	CheckError(err)
	fmt.Print(string(result))
}
View Source
var OpenNewTab = func() {
	_, err := util.RunAS(getNewTabScript())

	if err != nil {
		OpenNewWindow()
	}
}
View Source
var OpenNewWindow = func() {
	_, err := util.RunAS(getNewWindowScript())
	CheckError(err)
}
View Source
var ParseQueryFlags = func(userQuery string) (input string, options map[string]string) {
	options = make(map[string]string)

	for _, args := range strings.Split(userQuery, " ") {
		reg, err := regexp.Compile("--[a-zA-Z\\d]*")
		CheckError(err)
		argList := strings.Split(args, " ")

		for _, arg := range argList {
			if reg.MatchString(arg) {
				key := strings.Split(strings.Split(arg, "--")[1], "=")[0]
				value := strings.Split(arg, "=")[1]
				options[key] = value
			} else {
				input += (arg + " ")
			}
		}
	}

	if strings.HasSuffix(input, " ") {
		input = strings.Trim(input, " ")
	}

	return
}

Used only in fetchBookmark.go of`chf` command

View Source
var ParseUserQuery = func(query string) (titleQuery string, domainQuery string, isDomainSearch bool) {
	titleQuery = ""
	domainQuery = ""
	isDomainSearch = false

	if strings.Contains(query, "#") || strings.Contains(query, "@") {
		var words = strings.Split(query, " ")

		for _, word := range words {

			if strings.HasPrefix(word, "#") && len(word) > 1 {
				isDomainSearch = true
				domainQuery = word[1 : len(word)-1]
			} else {

				if titleQuery == "" {
					titleQuery += word
				} else {
					titleQuery += " " + word
				}
			}
		}
	} else {
		titleQuery = query
	}

	return
}

Used in `chs`, `chh`

View Source
var RunWorkflowHelper = func(wf *aw.Workflow, query string) {
	wf.CheckForUpdate()
	wf.Configure(aw.SuppressUIDs(true))

	if wf.UpdateAvailable() {
		log.Println("Workflow Update Available!")

		wf.NewItem("Workflow Update Available!").
			Subtitle("⇥ or ↩ to install update").
			Valid(true).
			Icon(iconUpdateAvailable).
			Var("update", "true")
	} else {
		wf.NewItem("Workflow Is Up To Date").
			Subtitle("").
			Valid(false).
			Icon(iconUpdateOK)
	}

	wf.NewItem("View Help File").
		Subtitle("Open workflow help in your browser").
		Valid(true).
		Icon(iconHelp).
		Var("url", "https://github.com/jopemachine/alfred-chromium-workflow/blob/master/README.md")

	wf.NewItem("Report Issue").
		Subtitle("Open workflow issue tracker in your browser").
		Icon(iconIssue).
		Var("url", "https://github.com/jopemachine/alfred-chromium-workflow/issues").
		Valid(true)

	wf.NewItem("Visit Forum Thread").
		Subtitle("Open workflow thread on alfredforum.com in your browser").
		Icon(iconForum).
		Var("url", "https://www.alfredforum.com/topic/18380-chromium-based-browser-workflow-supporting-browser-profile-switching/").
		Valid(true)

	wf.NewItem("Cache Favicons Manually").
		Subtitle("").
		Valid(true).
		Var("cacheFavicons", "true")

	if query != "" {
		wf.Filter(query)
	}
}
View Source
var SelectBrowser = func(wf *aw.Workflow, query string) {
	browsers := []string{
		"Chrome",
		"Chrome Beta",
		"Chrome Canary",
		"Chromium",
		"Edge",
		"Edge Canary",
		"Brave",
		"Naver Whale",
		"Vivaldi",
		"Opera",
		"Epic",
		"Arc",
	}

	for _, browser := range browsers {
		if CheckBrowserIsInstalled(browser) {
			addNewBrowserItem(wf, browser)
		}
	}

	if query != "" {
		wf.Filter(query)
	}
}
View Source
var SelectProfile = func(wf *aw.Workflow, query string) {
	profileRoot := GetProfileRootPath(Conf.Browser)
	profileFilePaths, err := filepath.Glob(profileRoot + "/" + "Profile *")
	CheckError(err)
	defaultProfileFilePath, err := filepath.Glob(profileRoot + "/" + "Default")
	CheckError(err)

	profileFilePaths = append(defaultProfileFilePath, profileFilePaths...)

	var profiles []string

	for _, profileFilePath := range profileFilePaths {
		profileFilePathArr := strings.Split(profileFilePath, "/")
		profiles = append(profiles, profileFilePathArr[len(profileFilePathArr)-1])
	}

	possibleProfiles := profiles

	if Conf.CustomizedProfiles != "" {
		possibleProfiles = append(strings.Split(Conf.CustomizedProfiles, ","), profiles...)
	}

	for _, profile := range possibleProfiles {
		title := profile

		if Conf.Profile == profile {
			title = "[✔] " + profile
		}

		profileImgPath := GetDBFilePath(Conf.Browser, profile, "Google Profile Picture.png")

		item := wf.NewItem(title).
			Valid(true).
			Arg(profile).
			Autocomplete(profile)

		if FileExist(profileImgPath) {
			item.Icon(&aw.Icon{profileImgPath, ""})
		}
	}

	if query != "" {
		wf.Filter(query)
	}
}
View Source
var TraverseBookmarkArray func(item []interface{}, options TraverseBookmarkJsonOption) []BookmarkItem
View Source
var TraverseBookmarkJSONObject func(item map[string]interface{}, options TraverseBookmarkJsonOption) []BookmarkItem

InitBookmarkJsonTraversal should be called first before calling this function

View Source
var UpdateWorkflow = func(wf *aw.Workflow) {
	if wf.UpdateAvailable() {
		wf.InstallUpdate()
	}
}

Functions

func CopyFile

func CopyFile(src, dst string)

func StringContains

func StringContains(slice []string, item string) bool

TODO: Replace below function with stdlib's one when it is merged Ref: https://stackoverflow.com/questions/10485743/contains-method-for-a-slice

Types

type BookmarkItem

type BookmarkItem struct {
	Id       string        `json:"id"`
	Url      string        `json:"url,omitempty"`
	Name     string        `json:"name,omitempty"`
	Children []interface{} `json:"children,omitempty"`
}

type TraverseBookmarkJsonOption

type TraverseBookmarkJsonOption struct {
	Targets []string
	Depth   int
}

type WorkflowConfig

type WorkflowConfig struct {
	Browser            string
	Locale             string
	Profile            string
	CustomizedProfiles string
	ResultCountLimit   int
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL