diff --git a/.github/workflows/pr-packager.yml b/.github/workflows/pr-packager.yml index 921a2c2..d968a10 100644 --- a/.github/workflows/pr-packager.yml +++ b/.github/workflows/pr-packager.yml @@ -10,12 +10,12 @@ jobs: runs-on: windows-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Set up Python ${{ env.PYTHON_VER }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ env.PYTHON_VER }} - - uses: actions/cache@v2 + - uses: actions/cache@v4 with: path: ~\AppData\Local\pip\Cache key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} @@ -27,7 +27,7 @@ jobs: pip install wheel pip install -r ./requirements.txt -t ./lib - name: Upload - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: artifact path: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9904519..1bb01a1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,14 +18,14 @@ jobs: runs-on: windows-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up Python ${{ env.PYTHON_VER }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ env.PYTHON_VER }} - - uses: actions/cache@v2 + - uses: actions/cache@v4 if: startsWith(runner.os, 'Windows') with: path: ~\AppData\Local\pip\Cache diff --git a/.github/workflows/test-plugin.yml b/.github/workflows/test-plugin.yml index ec00b73..38ceccd 100644 --- a/.github/workflows/test-plugin.yml +++ b/.github/workflows/test-plugin.yml @@ -22,7 +22,7 @@ jobs: python_ver: ['3.8'] steps: - name: Checkout Plugin Repo - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: path: ${{github.event.repository.name}} - name: Get Plugin's version @@ -66,7 +66,7 @@ jobs: echo "FILE_NAME=$file_name" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append echo "TAG_NAME=$tag_name" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append - name: Flow Launcher Cache - uses: actions/cache@v2 + uses: actions/cache@v4 id: flow_cache with: path: | @@ -95,10 +95,10 @@ jobs: New-Item -ItemType SymbolicLink -Path $plugin_path -Target $repo_path echo "PLUGIN_PATH=$plugin_path" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python_ver }} - - uses: actions/cache@v2 + - uses: actions/cache@v4 with: path: ~\AppData\Local\pip\Cache key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} diff --git a/SettingsTemplate.yaml b/SettingsTemplate.yaml index fffdb39..ec3f5df 100644 --- a/SettingsTemplate.yaml +++ b/SettingsTemplate.yaml @@ -9,6 +9,9 @@ body: - Firefox - Edge - Brave + - Brave Nightly - Opera - Vivaldi - - Arc \ No newline at end of file + - Arc + - Zen + - Floorp \ No newline at end of file diff --git a/plugin.json b/plugin.json index 16e9fb4..3006b03 100644 --- a/plugin.json +++ b/plugin.json @@ -4,7 +4,7 @@ "Name": "Browser History", "Description": "Search your Web Browser history", "Author": "Garulf", - "Version": "0.6.0", + "Version": "0.8.1", "Language": "python", "Website": "https://github.com/Garulf/browser-history", "IcoPath": "./icon.png", diff --git a/plugin/browsers.py b/plugin/browsers.py index 64d71fb..c6b10cb 100644 --- a/plugin/browsers.py +++ b/plugin/browsers.py @@ -14,9 +14,12 @@ FIREFOX_DIR = Path(ROAMING, 'Mozilla', 'Firefox', 'Profiles') EDGE_DIR = Path(LOCAL_DATA, 'Microsoft', 'Edge', 'User Data', 'Default', 'History') BRAVE_DIR = Path(LOCAL_DATA, 'BraveSoftware', 'Brave-Browser', 'User Data', 'Default', 'History') +BRAVE_NIGHTLY_DIR = Path(LOCAL_DATA, 'BraveSoftware', 'Brave-Browser-Nightly', 'User Data', 'Default', 'History') OPERA_DIR = Path(ROAMING, 'Opera Software', 'Opera Stable', 'Default', 'History') VIVALDI_DIR = Path(LOCAL_DATA, 'Vivaldi', 'User Data', 'Default', 'History') ARC_DIR = Path(LOCAL_DATA, 'Packages', 'TheBrowserCompany.Arc_ttt1ap7aakyb4', 'LocalCache', 'Local', 'Arc', 'User Data', 'Default', 'History') +ZEN_DIR = Path(ROAMING, 'zen', 'Profiles') +Floorp_DIR = Path(ROAMING, 'Floorp', 'Profiles') def get(browser_name): if browser_name == 'chrome': @@ -27,12 +30,18 @@ def get(browser_name): return Edge() elif browser_name == 'brave': return Brave() + elif browser_name == 'brave nightly': + return BraveNightly() elif browser_name == 'opera': return Opera() elif browser_name == 'vivaldi': return Vivaldi() elif browser_name == 'arc': return Arc() + elif browser_name == 'zen': + return Zen() + elif browser_name == 'floorp': + return Floorp() else: raise ValueError('Invalid browser name') @@ -135,6 +144,19 @@ def history(self, limit=10): """ recents = self.query_history(self.database_path, 'SELECT url, title, last_visit_time FROM urls ORDER BY last_visit_time DESC', limit) return self.get_history_items(recents) + +class BraveNightly(Base): + """Brave Nightly Browser History""" + + def __init__(self, database_path=BRAVE_NIGHTLY_DIR): + self.database_path = database_path + + def history(self, limit=10): + """ + Returns a list of the most recently visited sites in Brave's history. + """ + recents = self.query_history(self.database_path, 'SELECT url, title, last_visit_time FROM urls ORDER BY last_visit_time DESC', limit) + return self.get_history_items(recents) class Opera(Base): """Opera Browser History""" @@ -174,6 +196,40 @@ def history(self, limit=10): """ recents = self.query_history(self.database_path, 'SELECT url, title, last_visit_time FROM urls ORDER BY last_visit_time DESC', limit) return self.get_history_items(recents) + +class Zen(Base): + """Zen Browser History""" + + def __init__(self, database_path=ZEN_DIR): + # Zen database is not in a static location, so we need to find it + self.database_path = self.find_database(database_path) + + def find_database(self, path): + """Find database in path""" + release_folder = Path(path).glob('*.Default (alpha)').__next__() + return Path(path, release_folder, 'places.sqlite') + + def history(self, limit=10): + """Most recent Zen history""" + recents = self.query_history(self.database_path, 'SELECT url, title, visit_date FROM moz_places INNER JOIN moz_historyvisits on moz_historyvisits.place_id = moz_places.id ORDER BY visit_date DESC', limit) + return self.get_history_items(recents) + +class Floorp(Base): + """Floorp Browser History""" + + def __init__(self, database_path=Floorp_DIR): + # Floorp database is not in a static location, so we need to find it + self.database_path = self.find_database(database_path) + + def find_database(self, path): + """Find database in path""" + release_folder = Path(path).glob('*.default-release').__next__() + return Path(path, release_folder, 'places.sqlite') + + def history(self, limit=10): + """Most recent Firefox history""" + recents = self.query_history(self.database_path, 'SELECT url, title, visit_date FROM moz_places INNER JOIN moz_historyvisits on moz_historyvisits.place_id = moz_places.id ORDER BY visit_date DESC', limit) + return self.get_history_items(recents) class HistoryItem(object): """Representation of a history item""" @@ -198,7 +254,13 @@ def timestamp(self): return datetime((self.last_visit_time/1000000)-11644473600, 'unixepoch', 'localtime') elif isinstance(self.browser, (Brave)): return datetime((self.last_visit_time/1000000)-11644473600, 'unixepoch', 'localtime') + elif isinstance(self.browser, (BraveNightly)): + return datetime((self.last_visit_time/1000000)-11644473600, 'unixepoch', 'localtime') elif isinstance(self.browser, (Opera)): return datetime((self.last_visit_time/1000000)-11644473600, 'unixepoch', 'localtime') elif isinstance(self.browser, (Vivaldi)): return datetime((self.last_visit_time/1000000)-11644473600, 'unixepoch', 'localtime') + elif isinstance(self.browser, (Zen)): + return datetime.fromtimestamp(self.last_visit_time / 1000000.0) + elif isinstance(self.browser, (Firefox)): + return datetime.fromtimestamp(self.last_visit_time / 1000000.0) \ No newline at end of file diff --git a/plugin/main.py b/plugin/main.py index 5450565..cde7a4f 100644 --- a/plugin/main.py +++ b/plugin/main.py @@ -1,5 +1,6 @@ -from flox import Flox, ICON_HISTORY, ICON_BROWSER +from flox import Flox, ICON_HISTORY, ICON_BROWSER, ICON_FILE +import pyperclip import browsers HISTORY_GLYPH = '' @@ -53,6 +54,18 @@ def context_menu(self, data): parameters=[data[1]], ) + self.add_item( + title='Copy to clipboard', + subtitle=data[1], + icon=ICON_FILE, + method=self.copy_to_clipboard, + parameters=[data[1]], + + ) + + def copy_to_clipboard(self, data): + pyperclip.copy(data) + self.show_msg("Copied!", f"{data}") if __name__ == "__main__": BrowserHistory() diff --git a/requirements.txt b/requirements.txt index 151f5b3..07a519c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ flox-lib==0.10.4 +pyperclip==1.9.0