├── .gitignore ├── README.md ├── demo.gif └── src └── searchSafariHistory.py /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Alfred Safari History Search 2 | 3 | Search Safari browse history from Alfred. Support Sierra, High Sierra adn Mojave. (Earlier os untested) 4 | 5 | ## Demo 6 | 7 | ![][demo] 8 | 9 | ## Note for MacOS 10.14 Mojave users 10 | 11 | If you got the `unable to open database file` error, go to `System Preferences > Security & Privacy > Privacy > Full Disk Access` and give `Alfred 3.app` permission to access Safari data :) 12 | 13 | ## Download 14 | 15 | Get Alfred Safari History Search from [GitHub][gh-releases]. 16 | 17 | ## Usage 18 | 19 | - `hsi` — Show list of recent 20 Safari browse history 20 | - `hsi ` — Search for history matching `` 21 | - `↩` or `⌘+NUM` — Open URL in browser 22 | - `⇧` or `⌘+Y` — Show Quick Look preview of URL 23 | - `⌘+L` — Show full title, URL, browse date in Alfred's Large Type window 24 | - `⌘+C` - Copy link URL 25 | 26 | ## Licensing 27 | 28 | [MIT][mit] 29 | 30 | [mit]: http://opensource.org/licenses/MIT 31 | [gh-releases]: https://github.com/rx2130/alfred-safari-history-search/releases 32 | [demo]: https://raw.githubusercontent.com/rx2130/alfred-safari-history-search/master/demo.gif 33 | -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rx2130/alfred-safari-history-search/dbd3334c149f62ecec20f3da656a75f3ea6c2281/demo.gif -------------------------------------------------------------------------------- /src/searchSafariHistory.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import json 3 | import sqlite3 4 | import os 5 | from datetime import datetime 6 | 7 | 8 | PATH = os.path.expanduser("~/Library/Safari/History.db") 9 | HISTORY_LIMIT = 40 10 | 11 | 12 | def searchSafariHistory(): 13 | query = ["%{}%".format(w) for w in sys.argv[1].split(" ") if w] 14 | 15 | sql = f""" 16 | SELECT title, url, visit_time + 978307200, title || ' ' || url AS s 17 | FROM history_visits AS v 18 | INNER JOIN history_items AS i 19 | ON v.history_item = i.id 20 | WHERE title <> '' 21 | {"AND s LIKE ? " * len(query)} 22 | ORDER BY visit_time DESC 23 | LIMIT {HISTORY_LIMIT} 24 | """ 25 | 26 | with sqlite3.connect(PATH) as con: 27 | return con.execute(sql, query) 28 | 29 | 30 | def timeBeautify(time): 31 | res = None 32 | time = datetime.fromtimestamp(time) 33 | now = datetime.now() 34 | if time.date() == now.date(): 35 | res = time.strftime("%-I:%M %p") 36 | else: 37 | res = time.strftime("%A,%B %-d,%Y") 38 | return "[{}] ".format(res) 39 | 40 | 41 | def main(): 42 | items = [] 43 | for r in searchSafariHistory(): 44 | title, url, time, _ = r 45 | time = timeBeautify(time) 46 | items.append( 47 | { 48 | "title": title, 49 | "subtitle": time + url, 50 | "arg": url, 51 | "text": { 52 | "copy": url, 53 | "largetype": "{}\n{}\n{}".format(title, url, time), 54 | }, 55 | } 56 | ) 57 | print(json.dumps({"items": items})) 58 | 59 | 60 | if __name__ == "__main__": 61 | main() 62 | --------------------------------------------------------------------------------