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 IsEmptyDirectory ¶
Ref: https://stackoverflow.com/questions/30697324/how-to-check-if-directory-on-path-is-empty
func StringContains ¶
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 ¶
Click to show internal directories.
Click to hide internal directories.