Skip to content

Commit

Permalink
rename modules to allow for further extension (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
seanbreckenridge committed Jan 30, 2022
1 parent e361ce8 commit 8a19748
Show file tree
Hide file tree
Showing 41 changed files with 107 additions and 79 deletions.
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
### 2022-01-30

[Relevant PR](https://github.com/seanbreckenridge/HPI/pull/18)

Renamed some modules to allow for future extension, and less possibilities for conflicts with other related HPI modules under a particular company/service/source

For reference, [here is the current directory structure](https://github.com/seanbreckenridge/HPI/tree/eb425e653918d68eb9d41da29e791fe1ba554dc7/my) as of this commit

In particular, anything with a `gdpr`/`data_export`/`privacy_export` is named to be that, instead of globally squashing the namespace module to the single `modulename.py` file

Converting a single-file module to a namespace module [is always a breaking change](https://github.com/karlicoss/promnesia/pull/225#issuecomment-819773697), and though [one can do hacky traceback introspection](https://github.com/karlicoss/HPI/blob/master/my/reddit/__init__.py) (to possible delay the change from a non-namespace package to a namespace package. However, if anyone else is using this code, its likely in the background through promnesia, so most likely situation is that they don't see that till I deprecate it anyways), but its only a temporary solution until the `__init__.py`/`module.py` file is eventually removed -- so better to do them all now instead of waiting till it becomes 'too late'

A user (or me) may want to write their own module with the same name, meaning they can't use both at the same time if mine is just `my.module_name.py`, since my module existing means any other namespace packages can't have the same base name (see [reorder_editable](https://github.com/seanbreckenridge/reorder_editable) for an explanation)

The one motivating this change is `apple.py`, since the old `apple.py` was parsing the privacy export, but I wanted to add something to parse [`imessage`](https://github.com/seanbreckenridge/HPI/commit/e361ce8182d8be8b331875078ad17605d3f80a50) files. Someone else may want to add other `apple/file.py` files to parse other parts of apple/mac behaviour, but me having the single `apple.py` either means they have to have their repo before mine on their path (but doing so means they overwrite the current `apple.py` file, so they cant use that to parse their privacy export, even if they were trying to do something else entirely), or they have to rename their code to something like `my_apple/file.py` to create a new namespace module

Possible 'Exceptions' to this:

- For some files, if the possibility for conflict is low (I can't imagine anyone exporting data from the source in any other way, e.g., `ipython`, `project_euler`) or the name is so specific to the source that its not needed (e.g. `ttt`, `window_watcher`)
- For files where I can't imagine you'd want both mine and your/custom implementation the same time, e.g. if you override `bash`, `zsh`, you're probably creating your own solution to parse that source, and don't need mine (If that's not the case, feel free to open an issue)
- For some of my modules, I've renamed them from what they do to their service/project names instead (`albums` to `nextalbums`; `money` to `mint`), so I'm not holding the generic name of some function when I don't really need to
52 changes: 27 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,40 +17,40 @@ This is built on top of [`karlicoss/HPI`](https://github.com/karlicoss/HPI). It

### My Modules

- `my.browsing`, using [`browserexport`](https://github.com/seanbreckenridge/browserexport) to backup/parse firefox/chrome/safari history
- `my.browser.export`, using [`browserexport`](https://github.com/seanbreckenridge/browserexport) to backup/parse firefox/chrome/safari history
- `my.zsh` and `my.bash`, access to my shell history w/ timestamps
- `my.imap` to parse local IMAP sync's of my email
- `my.google_takeout`, parses lots of (~500,000) events (youtube, searches, phone usage, comments, location history) from [google takeouts](https://takeout.google.com/), using [`google_takeout_parser`](https://github.com/seanbreckenridge/google_takeout_parser)
- `my.mpv`, accesses movies/music w/ activity/metdata that have played on my machine, facilitated by a [mpv history daemon](https://github.com/seanbreckenridge/mpv-history-daemon)
- `my.discord`, parses ~1,000,000 messages/events from the discord data export, parser [here](https://github.com/seanbreckenridge/discord_data)
- `my.money`, bank account transactions/balance history from [my personal budget tool](https://github.com/seanbreckenridge/mint)
- `my.mpv.history_daemon`, accesses movies/music w/ activity/metdata that have played on my machine, facilitated by a [mpv history daemon](https://github.com/seanbreckenridge/mpv-history-daemon)
- `my.discord.data_export`, parses ~1,000,000 messages/events from the discord data export, parser [here](https://github.com/seanbreckenridge/discord_data)
- `my.mint`, bank account transactions/balance history from [my personal budget tool](https://github.com/seanbreckenridge/mint)
- `my.todotxt`, to track my to-do list history (using backups of my [`todotxt`](http://todotxt.org/) files)
- `my.newsboat`, keeps track of when I added/removed RSS feeds (for [`newsboat`](https://newsboat.org/))
- `my.rss.newsboat`, keeps track of when I added/removed RSS feeds (for [`newsboat`](https://newsboat.org/))
- `my.ipython`, for timestamped python REPL history
- `my.ttt`, to parse shell/system history tracked by [`ttt`](https://github.com/seanbreckenridge/ttt)
- `my.window_watcher`, to parse active window events (what application I'm using/what the window title is) using [`window_watcher`](https://github.com/seanbreckenridge/aw-watcher-window)
- `my.location`, merges data from [`gpslogger`](https://github.com/mendhak/gpslogger), `apple`, `google`, `discord`, `blizzard`, and `facebook` to provide location data (goes back ~10 years)
- `my.chess`, to track my [chess.com](https://www.chess.com)/[lichess.org](https://lichess.org/) games, using [`chess_export`](https://github.com/seanbreckenridge/chess_export)
- `my.trakt`, providing me a history/my ratings for Movies/TV Show (episodes) using [`traktexport`](https://github.com/seanbreckenridge/traktexport)
- `my.listenbrainz`, exporting my music scrobbling history from [ListenBrainz](https://listenbrainz.org/) (open-source Last.fm) using [`listenbrainz_export`](https://github.com/seanbreckenridge/listenbrainz_export)
- `my.mal`, for anime/manga history using [`malexport`](https://github.com/seanbreckenridge/malexport)
- `my.grouvee`, for my video game history/backlog using [`grouvee_export`](https://github.com/seanbreckenridge/grouvee_export)
- `my.runelite`, parses data from the [automatic runelite screenshots](https://github.com/runelite/runelite/wiki/Screenshot)
- `my.chess.export`, to track my [chess.com](https://www.chess.com)/[lichess.org](https://lichess.org/) games, using [`chess_export`](https://github.com/seanbreckenridge/chess_export)
- `my.trakt.export`, providing me a history/my ratings for Movies/TV Show (episodes) using [`traktexport`](https://github.com/seanbreckenridge/traktexport)
- `my.listenbrainz.export`, exporting my music scrobbling history from [ListenBrainz](https://listenbrainz.org/) (open-source Last.fm) using [`listenbrainz_export`](https://github.com/seanbreckenridge/listenbrainz_export)
- `my.mal.export`, for anime/manga history using [`malexport`](https://github.com/seanbreckenridge/malexport)
- `my.grouvee.export`, for my video game history/backlog using [`grouvee_export`](https://github.com/seanbreckenridge/grouvee_export)
- `my.runelite.screenshots`, parses data from the [automatic runelite screenshots](https://github.com/runelite/runelite/wiki/Screenshot)
- `my.project_euler`, when I solved [Project Euler](https://projecteuler.net/) problems
- `my.albums`, grabbing when I listened to music albums/my ratings using my [giant spreadsheet](https://sean.fish/s/albums). Handled by [`nextalbums export`](https://github.com/seanbreckenridge/albums)
- `my.nextalbums`, grabbing when I listened to music albums/my ratings using my [giant spreadsheet](https://sean.fish/s/albums). Handled by [`nextalbums export`](https://github.com/seanbreckenridge/albums)

#### 'Historical' Modules

These are modules to parse GDPR exports/data from services I used to use, but don't anymore. They're here to provide more context into the past.

- `my.apple`, parses Game Center and location data from the apple GDPR export
- `my.facebook`, to parse the GDPR export from Facebook
- `my.league`, gives League of Legends game history using [`lolexport`](https://github.com/seanbreckenridge/lolexport)
- `my.steam`, for steam achievement data and game playtime using [`steamscraper`](https://github.com/seanbreckenridge/steamscraper)
- `my.blizzard`, for general battle.net event data [parsed from a GDPR export](https://github.com/seanbreckenridge/blizzard_gdpr_parser)
- `my.apple.privacy_export`, parses Game Center and location data from the apple GDPR export
- `my.facebook.gdpr`, to parse the GDPR export from Facebook
- `my.league.export`, gives League of Legends game history using [`lolexport`](https://github.com/seanbreckenridge/lolexport)
- `my.steam.scraper`, for steam achievement data and game playtime using [`steamscraper`](https://github.com/seanbreckenridge/steamscraper)
- `my.blizzard.gdpr`, for general battle.net event data [parsed from a GDPR export](https://github.com/seanbreckenridge/blizzard_gdpr_parser)
- `my.old_forums`, parses random forum posts and achievements from sites I used to use in the past, see [`old_forums`](https://github.com/seanbreckenridge/old_forums)
- `my.skype` to parse a couple datetimes from the Skype GDPR export
- `my.spotify`, to parse the GDPR export from Spotify, mostly to access songs from my playlists from years ago
- `my.skype.gdpr` to parse a couple datetimes from the Skype GDPR export (seems all my data from years ago is long gone)
- `my.spotify.gdpr`, to parse the GDPR export from Spotify, mostly to access songs from my playlists from years ago
- `my.twitch`, merging the [data export](https://www.twitch.tv/p/en/legal/privacy-choices/#user-privacy-requests) and my messages parsed from the [overrustle logs dump](https://github.com/seanbreckenridge/overrustle_parser)

See [here](https://github.com/seanbreckenridge/dotfiles/blob/master/.config/my/my/config/__init__.py) for config.
Expand Down Expand Up @@ -111,8 +111,8 @@ Most common shell commands?
What websites do I visit most?

```python
>>> import collections, pprint, my.browsing, urllib
>>> pprint.pprint(collections.Counter([urllib.parse.urlparse(h.url).netloc for h in my.browsing.history()]).most_common(5))
>>> import collections, pprint, my.browser.export, urllib
>>> pprint.pprint(collections.Counter([urllib.parse.urlparse(h.url).netloc for h in my.browser.export.history()]).most_common(5))
[('github.com', 20953),
('duckduckgo.com', 10146),
('www.youtube.com', 10126),
Expand All @@ -123,9 +123,9 @@ What websites do I visit most?
Song I've listened to most?

```python
>>> import collections, my.mpv
>>> collections.Counter([m.path for m in my.mpv.history()]).most_common(1)[0][0]
'/home/sean/Music/Toby Fox/Toby Fox - UNDERTALE Soundtrack (2015) [V0]/085 - Fallen Down (Reprise).mp3'
>>> import collections, my.mpv.history_daemon
>>> collections.Counter([m.path for m in my.mpv.history_daemon.history()]).most_common(1)[0][0]
'/home/sean/Music/JPEFMAFIA/JPEGMAFIA - LP! - 2021 - V0/JPEGMAFIA - LP! - 05 HAZARD DUTY PAY!.mp3'
```

Movie I've watched most?
Expand All @@ -150,7 +150,7 @@ The [`install` script here](https://github.com/seanbreckenridge/HPI/blob/a6495ad

For more information on that, and some of the complications one can run into, see [reorder_editable](https://github.com/seanbreckenridge/reorder_editable#editable-namespace-packages), and the [module design](https://github.com/karlicoss/HPI/blob/master/doc/MODULE_DESIGN.org#adding-new-modules) docs for HPI.

Disregarding setting up all the dependencies for individual modules (which is why the [`install`](install) script exists), this is setup by doing:
Disregarding setting up all the dependencies for individual (e.g. `my.ipython`) modules (which is why the [`install`](install) script exists), this is setup by doing:

```bash
# clone and install upstream as an editable package
Expand All @@ -168,6 +168,8 @@ python3 -m reorder_editable reorder ./HPI ./HPI-fork

Those directories are editable installs, meaning any changes I make to them get applied immediately, which is very convenient for debugging and developing new modules.

If you have issues installing, check the [CHANGELOG](CHANGELOG.md) for any possible breaking changes

[`jobs`](./jobs) contains anacron-like jobs that are run periodically, using [`bgproc`](https://github.com/seanbreckenridge/bgproc) and [`evry`](https://github.com/seanbreckenridge/evry). So, this repo contains both the [DAL](https://beepb00p.xyz/exports.html#dal) and scripts to backup my data. I run the jobs in the background using supervisor, see [here](https://github.com/seanbreckenridge/dotfiles/tree/master/.local/scripts/supervisor) for the config, and/or [`run_jobs`](https://github.com/seanbreckenridge/dotfiles/blob/master/.local/scripts/supervisor/run_jobs) for the `bgproc` wrapper. (They likely won't work out of the box for you, as they depend on tokens/environment variables that are set on my system - In particular the `HPIDATA` environment variable, which for me is `~/data`)

### TODO:
Expand Down
16 changes: 8 additions & 8 deletions functions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ filter_unique() {
# my.albums
#############

alias albums-history='hpi query my.albums.history'
alias albums-to-listen='hpi query my.albums.to_listen'
alias albums-history='hpi query my.nextalbums.history'
alias albums-to-listen='hpi query my.nextalbums.to_listen'
# how many albums I have on my list that I havent listened to yet
alias albums-left='albums-to-listen | jq length'
# pipe a list of album blobs to this to describe them
Expand All @@ -30,15 +30,15 @@ albums-describe-score() {
jq -r '"[\(.score) | \(.listened_on)] \(.cover_artists) - \(.album_name) (\(.year))"'
}
# any albums which I can't find/have to order physical copies for to listen to
alias albums-cant-find="hpi query -s my.albums._albums_cached | jq -r 'select(.note==\"cant find\")' | albums-describe"
alias albums-cant-find="hpi query -s my.nextalbums._albums_cached | jq -r 'select(.note==\"cant find\")' | albums-describe"
# list any albums I have yet to listen to, sorted by how many awards they've won
albums-awards() {
local COUNT="${1:-10}"
albums-to-listen | jq -r "sort_by(.reasons | length) | reverse | .[0:${COUNT}] | .[] | \"[\(.reasons | length)] \(.album_name) - \(.cover_artists) (\(.year))\""
}
# just the next albums I should listen to chronologically
albums-next() {
hpi query my.albums.to_listen -s --limit "${1:-10}" | albums-describe
hpi query my.nextalbums.to_listen -s --limit "${1:-10}" | albums-describe
}
alias albums-next-all='albums-next 99999'
alias albums-history-desc='albums-history -s | albums-describe-score'
Expand All @@ -62,7 +62,7 @@ albums-filter-genre() {
###################

scrobbles() {
hpi query my.listenbrainz.history -s "$@"
hpi query my.listenbrainz.export.history -s "$@"
}
scrobble-describe() {
jq -r '"\(.listened_at) \(.artist_name) - \(.track_name)"'
Expand All @@ -74,7 +74,7 @@ scrobble-describe() {

# functions to replay music I've listened to recently
mpv-recent() {
hpi query my.mpv.history --order-type datetime --reverse -s --limit "${1:-1}"
hpi query my.mpv.history_daemon.history --order-type datetime --reverse -s --limit "${1:-1}"
}
mpv-recent-path() {
mpv-recent "$1" | jq -r .path
Expand All @@ -98,12 +98,12 @@ alias zsh-unique-fzf='zsh-unique | fzf'

# e.g. trakt-movies --recent 4w | trakt-describe-movie
trakt-movies() {
hpi query 'my.trakt.history' -s "$@" | trakt-filter-movies
hpi query 'my.trakt.export.history' -s "$@" | trakt-filter-movies
}

# e.g. trakt-episodes --recent 4w | trakt-describe-episode
trakt-episodes() {
hpi query 'my.trakt.history' -s "$@" | trakt-filter-episodes
hpi query 'my.trakt.export.history' -s "$@" | trakt-filter-episodes
}

trakt-filter-movies() {
Expand Down
24 changes: 12 additions & 12 deletions install
Original file line number Diff line number Diff line change
Expand Up @@ -107,24 +107,24 @@ module_dependencies() {
hpi_module my.pdfs || return $?
hpi_module my.window_watcher || return $?
hpi_module my.smscalls || return $?
hpi_module my.browsing || return $?
hpi_module my.discord || return $?
hpi_module my.browser.export || return $?
hpi_module my.discord.data_export || return $?
hpi_module my.google_takeout || return $?
hpi_module my.time.tz.via_location || return $?
hpi_module my.coding.commits || return $?
hpi_module my.todotxt || return $?
hpi_module my.todotxt.file_backups || return $?
hpi_module my.location.ip || return $?
hpi_module my.location.gpslogger || return $?
hpi_module my.chess || return $?
hpi_module my.mpv || return $?
hpi_module my.league || return $?
hpi_module my.trakt || return $?
hpi_module my.imap || return $?
hpi_module my.grouvee || return $?
hpi_module my.mal || return $?
hpi_module my.listenbrainz || return $?
hpi_module my.chess.export || return $?
hpi_module my.mpv.history_daemon || return $?
hpi_module my.league.export || return $?
hpi_module my.trakt.export || return $?
hpi_module my.mail.imap || return $?
hpi_module my.grouvee.export || return $?
hpi_module my.mal.export || return $?
hpi_module my.listenbrainz.export || return $?
hpi_module my.old_forums || return $?
hpi_module my.skype || return $?
hpi_module my.skype.gdpr || return $?
}

verify_personal_python_packages() {
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion my/bash.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
from my.core import get_files, Stats, LazyLogger, Paths, dataclass
from my.core.common import mcachew
from my.utils.time import parse_datetime_sec
from my.utils.common import InputSource
from my.utils.input_source import InputSource


@dataclass
Expand Down
4 changes: 2 additions & 2 deletions my/blizzard.py → my/blizzard/gdpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ class config(user_config):
from itertools import chain

from my.core import get_files, Stats
from .utils.time import parse_datetime_sec
from .utils.common import InputSource
from my.utils.time import parse_datetime_sec
from my.utils.input_source import InputSource


logger = LazyLogger(__name__, level="warning")
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion my/chess.py → my/chess/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

from my.core import get_files, Stats, LazyLogger, Paths, dataclass
from my.core.common import mcachew
from my.utils.common import InputSource
from my.utils.input_source import InputSource


@dataclass
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion my/facebook.py → my/facebook/gdpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class config(user_config):


from my.core import get_files, Stats, Res, Json, LazyLogger
from .utils.time import parse_datetime_sec
from my.utils.time import parse_datetime_sec


logger = LazyLogger(__name__, level="warning")
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion my/ipython.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class config(user_config):
from IPython.core.history import HistoryAccessor # type: ignore[import]

from my.core import get_files, warn_if_empty, Stats, Res
from .utils.common import InputSource
from my.utils.input_source import InputSource


class Command(NamedTuple):
Expand Down
4 changes: 2 additions & 2 deletions my/league.py → my/league/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ class config(user_config):
from itertools import chain

from my.core import get_files, Stats, Res, Json, warn_if_empty
from .utils.time import parse_datetime_millis
from .utils.common import InputSource
from my.utils.time import parse_datetime_millis
from my.utils.input_source import InputSource


def inputs() -> Sequence[Path]:
Expand Down
2 changes: 1 addition & 1 deletion my/listenbrainz.py → my/listenbrainz/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from more_itertools import unique_everseen

from my.core import get_files, Stats, LazyLogger, Paths, dataclass
from my.utils.common import InputSource
from my.utils.input_source import InputSource


@dataclass
Expand Down
9 changes: 4 additions & 5 deletions my/location/all.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@
from .models import Location

# sources
from .ip import ips
from .gpslogger import history as gpslogger_history
from ..apple import events as apple_events
from ..apple import Location as AppleLocation
from my.location.ip import ips
from my.location.gpslogger import history as gpslogger_history
from my.apple.privacy_export import events as apple_events, Location as AppleLocation

from ..google_takeout import (
from my.google_takeout import (
events as google_events,
_cachew_depends_on as _google_cachew_depends_on,
)
Expand Down
2 changes: 1 addition & 1 deletion my/location/gpslogger.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class config(user_config):
from my.core import Stats, LazyLogger, Res
from my.core.common import get_files, warn_if_empty, mcachew
from my.core.warnings import high
from ..utils.common import InputSource
from my.utils.input_source import InputSource


logger = LazyLogger(__name__, level="warning")
Expand Down
Loading

0 comments on commit 8a19748

Please sign in to comment.