Merge pull request #38 from hughrun/2_5_release

2 5 release
This commit is contained in:
Hugh Rundle 2020-07-18 18:27:44 +10:00 committed by GitHub
commit 06ff0fe1f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 124 additions and 73 deletions

View File

@ -90,7 +90,7 @@ You can now enter the configuration details for each user:
| toots_to_keep | A list of toot ids indicating toots to be kept regardless of other settings. The ID of a toot is the last part of its individual URL. e.g. for [https://ausglam.space/@hugh/101294246770105799](https://ausglam.space/@hugh/101294246770105799) the id is `101294246770105799` |
| hashtags_to_keep | A list of hashtags, where any toots with any of these hashtags will be kept regardless of age. Do not include the '#' symbol. Do remember the [rules for hashtags](https://docs.joinmastodon.org/user/posting/#hashtags) |
| visibility_to_keep | Toots with any of the visibility settings in this list will be kept regardless of age. Options are: `public`, `unlisted`, `private`, `direct`. |
| archive | A string. The full toot is archived into individual files named by the toot's `id` in this writeable directory. |
| archive | A string representing the filepath to your toot archive. If this is provided, for every toot checked, the full toot is archived into individual files named by the toot's `id` in this writeable directory. Note that the default is for **all** toots to be archived, not just those that are being deleted. It is generally best to use an absolute file path - relative paths will not work if you call `ephemetoot` from another directory. |
All values other than `access_token`, `username` and `base_url` are optional, however if you include `toots_to_keep`, `hashtags_to_keep`, or `visibility_to_keep` you must make each a list, even if it is empty:
@ -105,9 +105,11 @@ If you want to use `ephemetoot` for multiple accounts, separate the config for e
# Running the script
For a short description of all available options, run `ephemetoot --help` from the command line.
It is **strongly recommended** that you do a test run before using `ephemetoot` live. There is no "undo"!
## Running in test mode
## Running in test mode (--test)
To do a test-run without actually deleting anything, run the script with the `--test` flag:
```shell
@ -123,7 +125,7 @@ ephemetoot
Depending on how many toots you have and how long you want to keep them, it may take a minute or two before you see any results.
## Specifying the config location
## Specifying the config location (--config)
By default ephemetoot expects there to be a config file called `config.yaml` in the directory from where you run the `ephemetoot` command. If you want to call it from elsewhere (e.g. with `cron`), you need to specify where your config file is:
@ -131,23 +133,37 @@ By default ephemetoot expects there to be a config file called `config.yaml` in
ephemetoot --config '~/directory/subdirectory/config.yaml'
```
## Slow down deletes to match API limit
## Slow down deletes to match API limit (--pace)
With the `--pace` flag, delete actions are slowed so that the API limit is never reached, using [`Mastodon.py`'s 'pace' method](https://mastodonpy.readthedocs.io/en/stable/index.html?highlight=pace#mastodon.Mastodon.__init__). This is recommended for your first run, as unless you have tooted fewer than 30 times you are guaranteed to hit the API limit for deletions the first time you run `ephemetoot`. If you do not toot very often on most days, it is probably more efficient to use the default behaviour for daily runs after the first time, but you can use `--pace` every time if you prefer.
## Hide skipped items
## Do more
If you skip a lot of items (e.g. you skip direct messages) it may clutter your log file to list these every time you run the script. You can suppress them from the output by using the `--hide_skipped` flag.
## Include datestamp with every action
### Include datestamp with every action (--datestamp)
If you want to know exactly when each delete action occured, you can use the `--datestamp` flag to add a datestamp to the log output. This is useful when using `--pace` so you can see the rate you have been slowed down to.
## Do less
### Hide skipped items (--hide-skipped)
If you skip a lot of items (e.g. you skip direct messages) it may clutter your log file to list these every time you run the script. You can suppress them from the output by using the `--hide-skipped` flag.
### Hide everything (--quiet)
Use the `--quiet` flag to suppress all logging except for the account name being checked and the number of toots deleted. Exception messages will not be suppressed.
### Only archive deleted toots (--archive-deleted)
If you provide a value for `archive` in your config file, the default is that all toots will be archived in that location, regardless of whether or not it is being deleted. i.e. it will create a local archive of your entire toot history. If you run ephemetoot with the `--test` flag, this allows you to use create an archive without even deleting anything.
You can use the `--archive-deleted` flag to only archive deleted toots instead.
## Combining flag options
You can use several flags together:
```shell
ephemetoot --config 'directory/config.yaml' --test --hide_skipped
ephemetoot --config 'directory/config.yaml' --test --hide-skipped
```
Use them in any order:
```shell

View File

@ -40,25 +40,31 @@ vnum = pkg_resources.require("ephemetoot")[0].version
parser = ArgumentParser()
parser.add_argument(
"--config", action="store", metavar="'filepath'", default="config.yaml", help="Filepath of your config file, relative to the current directory. If no --config path is provided, ephemetoot will use 'config.yaml'."
"--archive-deleted", action="store_true", help="Only archive toots that are being deleted"
)
parser.add_argument(
"--config", action="store", metavar="filepath", default="config.yaml", help="Filepath of your config file, absolute or relative to the current directory. If no --config path is provided, ephemetoot will use 'config.yaml'."
)
parser.add_argument(
"--datestamp", action="store_true", help="Include a datetime stamp for every action (e.g. deleting a toot)"
)
parser.add_argument(
"--hide_skipped", action="store_true", help="Do not write to log when skipping saved toots"
"--hide-skipped", "--hide_skipped", action="store_true", help="Do not write to log when skipping saved toots"
)
parser.add_argument(
"--pace", action="store_true", help="Slow deletion actions to match API rate limit to avoid pausing"
)
parser.add_argument(
"--schedule", action="store", metavar="'filepath'", nargs="?", const=".", help="Save and load plist file on MacOS"
"--quiet", action="store_true", help="Suppress most logging"
)
parser.add_argument(
"--schedule", action="store", metavar="filepath", nargs="?", const=".", help="Save and load plist file on MacOS"
)
parser.add_argument(
"--test", action="store_true", help="Do a test run without deleting any toots"
)
parser.add_argument(
"--time", action="store", metavar="'hours minutes'", nargs="*", help="Hour and minute to schedule: e.g. 9 30 for 9.30am"
"--time", action="store", metavar=('hour', 'minute'), nargs="*", help="Hour and minute to schedule: e.g. 9 30 for 9.30am"
)
parser.add_argument(
"--version", action="store_true", help="Display the version number"
@ -78,14 +84,14 @@ if __name__ == "__main__":
elif options.schedule:
ephemetoot.schedule(options)
else:
print('')
print('============= EPHEMETOOT v' + vnum + ' ================')
print('Running at ' + str( datetime.now(timezone.utc).strftime('%a %d %b %Y %H:%M:%S %z') ))
print('================================================')
print('')
if options.test:
print("This is a test run...")
if not options.quiet:
print('')
print('============= EPHEMETOOT v' + vnum + ' ================')
print('Running at ' + str( datetime.now(timezone.utc).strftime('%a %d %b %Y %H:%M:%S %z') ))
print('================================================')
print('')
if options.test:
print("This is a test run...\n")
with open(config_file) as config:
for accounts in yaml.safe_load_all(config):
for user in accounts:

View File

@ -11,7 +11,7 @@
# you can list only one user, or multiple users
# each user account should be preceded by a single dash, and indented, as per below
-
# ausglam.space account
# full example
access_token : ZA-Yj3aBD8U8Cm7lKUp-lm9O9BmDgdhHzDeqsY8tlL0
username : alice
base_url : ausglam.space
@ -27,9 +27,9 @@
visibility_to_keep :
- direct
- private
archive : ~/toots_archive/
archive : Users/alice/toots_archive/ausglam/
-
# aus.social account
# minimal example
# values other than access_token, username, and base_url are all optional
access_token : AZ-Yj3aBD8U8Cm7lKUp-lm9O9BmDgdhHzDeqsY8tlL9
username : bob

View File

@ -106,18 +106,31 @@ def checkToots(config, options, retry_count=0):
def checkBatch(timeline, deleted_count=0):
for toot in timeline:
if "id" in toot and "archive" in config:
filename = os.path.join(
config["archive"], str(toot["id"]) + ".json"
)
with open(filename, "w") as f:
f.write(json.dumps(toot, indent=4, default=jsondefault))
f.close()
# define archive path
if config["archive"][0] == '~':
archive_path = os.path.expanduser(config["archive"])
elif config["archive"][0] == '/':
archive_path = config["archive"]
else:
archive_path = os.path.join( os.getcwd(), config["archive"] )
if archive_path[-1] != '/':
archive_path += '/'
filename = os.path.join(archive_path, str(toot["id"]) + ".json")
if not options.archive_deleted:
# write toot to archive
with open(filename, "w") as f:
f.write(json.dumps(toot, indent=4, default=jsondefault))
f.close()
toot_tags = set()
for tag in toot.tags:
toot_tags.add(tag.name)
try:
if keep_pinned and hasattr(toot, "pinned") and toot.pinned:
if not options.hide_skipped:
if not (options.hide_skipped or options.quiet):
if options.datestamp:
print(
str(
@ -130,7 +143,7 @@ def checkToots(config, options, retry_count=0):
print("📌 skipping pinned toot - " + str(toot.id))
elif toot.id in toots_to_keep:
if not options.hide_skipped:
if not (options.hide_skipped or options.quiet):
if options.datestamp:
print(
str(
@ -143,7 +156,7 @@ def checkToots(config, options, retry_count=0):
print("💾 skipping saved toot - " + str(toot.id))
elif toot.visibility in visibility_to_keep:
if not options.hide_skipped:
if not (options.hide_skipped or options.quiet):
if options.datestamp:
print(
str(
@ -161,7 +174,7 @@ def checkToots(config, options, retry_count=0):
+ str(toot.id)
)
elif len(hashtags_to_keep.intersection(toot_tags)) > 0:
if not options.hide_skipped:
if not (options.hide_skipped or options.quiet):
if options.datestamp:
print(
str(
@ -175,53 +188,62 @@ def checkToots(config, options, retry_count=0):
print("#️⃣ skipping toot with hashtag - " + str(toot.id))
elif cutoff_date > toot.created_at:
if hasattr(toot, "reblog") and toot.reblog:
if options.datestamp:
print(
str(
datetime.now(timezone.utc).strftime(
"%a %d %b %Y %H:%M:%S %z"
)
),
end=" : ",
)
if not options.quiet:
if options.datestamp:
print(
str(
datetime.now(timezone.utc).strftime(
"%a %d %b %Y %H:%M:%S %z"
)
),
end=" : ",
)
print(
"👎 unboosting toot "
+ str(toot.id)
+ " boosted "
+ toot.created_at.strftime("%d %b %Y")
)
print(
"👎 unboosting toot "
+ str(toot.id)
+ " boosted "
+ toot.created_at.strftime("%d %b %Y")
)
deleted_count += 1
# unreblog the original toot (their toot), not the toot created by boosting (your toot)
if not options.test:
if mastodon.ratelimit_remaining == 0:
print(
"Rate limit reached. Waiting for a rate limit reset"
)
if not options.quiet:
print(
"Rate limit reached. Waiting for a rate limit reset"
)
# check for --archive-deleted
if options.archive_deleted and "id" in toot and "archive" in config:
# write toot to archive
with open(filename, "w") as f:
f.write(json.dumps(toot, indent=4, default=jsondefault))
f.close()
mastodon.status_unreblog(toot.reblog)
else:
if options.datestamp:
print(
str(
datetime.now(timezone.utc).strftime(
"%a %d %b %Y %H:%M:%S %z"
)
),
end=" : ",
)
if not options.quiet:
if options.datestamp:
print(
str(
datetime.now(timezone.utc).strftime(
"%a %d %b %Y %H:%M:%S %z"
)
),
end=" : ",
)
print(
"❌ deleting toot "
+ str(toot.id)
+ " tooted "
+ toot.created_at.strftime("%d %b %Y")
)
print(
"❌ deleting toot "
+ str(toot.id)
+ " tooted "
+ toot.created_at.strftime("%d %b %Y")
)
deleted_count += 1
time.sleep(
2
) # wait 2 secs between deletes to be a bit nicer to the server
if not options.test:
if mastodon.ratelimit_remaining == 0:
if mastodon.ratelimit_remaining == 0 and not options.quiet:
now = time.time()
diff = mastodon.ratelimit_reset - now
@ -237,6 +259,12 @@ def checkToots(config, options, retry_count=0):
+ str(format(diff / 60, ".0f"))
+ " minutes.\n"
)
# check for --archive-deleted
if options.archive_deleted and "id" in toot and "archive" in config:
# write toot to archive
with open(filename, "w") as f:
f.write(json.dumps(toot, indent=4, default=jsondefault))
f.close()
mastodon.status_delete(toot)
@ -333,10 +361,10 @@ def checkToots(config, options, retry_count=0):
print("Removed " + str(deleted_count) + " toots.")
print("")
print("---------------------------------------")
print("🥳 ==> 🧼 ==> 😇 User cleanup complete!")
print("---------------------------------------\n")
if not options.quiet:
print("\n---------------------------------------")
print("🥳 ==> 🧼 ==> 😇 User cleanup complete!")
print("---------------------------------------\n")
except IndexError:
print("No toots found!")
@ -361,7 +389,8 @@ def checkToots(config, options, retry_count=0):
account = mastodon.account(user_id)
timeline = mastodon.account_statuses(user_id, limit=40)
print("Checking " + str(account.statuses_count) + " toots")
if not options.quiet:
print("Checking " + str(account.statuses_count) + " toots")
checkBatch(timeline)

View File

@ -2,7 +2,7 @@ from setuptools import setup, find_packages
setup(
name="ephemetoot",
version="2.3.1",
version="2.5",
url="https://github.com/hughrun/ephemetoot",
license="GPL-3.0-or-later",
packages=find_packages(),