Merge pull request #33 from hughrun/community

Update Community documentation.
This commit is contained in:
Hugh Rundle 2020-07-04 16:43:16 +10:00 committed by GitHub
commit 75a09cb90f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 409 additions and 178 deletions

View File

@ -1,31 +1,32 @@
---
name: Bug report
about: Create a report to help us improve
title: 'BUG - '
title: 'BUG - x happens when y'
labels: bug
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**Description**
A clear description of what the bug is. Provide enough detail so that it is clear what the problem is. Include the exact text of any relevant error messages.
Please only log one bug per issue.
**Environment (please complete the following information):**
- OS: [e.g. MacOS 10.15.5 Catalina]
- Python version [e.g. 3.7.7]
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
Steps to reproduce the behavior. e.g. run with a particular flag or a particular config value.
**Expected behavior**
A clear and concise description of what you expected to happen.
**Actual behavior**
A clear and concise description of what actually happened.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Environment (please complete the following information):**
- OS: [e.g. MacOS]
- Python version [e.g. 3.7.7]
**Additional context**
Add any other context about the problem here.

View File

@ -1,18 +1,31 @@
---
name: Feature request
name: Feature proposal
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''
---
**Does your proposal relate to...**
- [ ] documentation
- [ ] what is displayed when running ephemetoot
- [ ] a new config value
- [ ] a new flag (option)
- [ ] something else
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
A clear and concise description of what the problem is. e.g. _I'm always frustrated when [...]_
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Would like to write the code yourself?**
- [ ] I would like to write the code myself and then log a pull request
- [ ] I would like someone else to write the code
- [ ] I would like someone to help me write the code
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

9
.github/pull_request_template.md vendored Normal file
View File

@ -0,0 +1,9 @@
Descriptive title for this pull request e.g. 'Add --cool_feature flag`
Changes in this pull request
-
-
-
Resolves #
Fixes #

76
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,76 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at ephemetoot AT ausglam DOT space. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq

View File

@ -1,4 +1,7 @@
A tool for deleting old toots, written in Python 3.
# 🥳 ==> 🧼 ==> 😇
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
**ephemetoot** is a Python command line tool for deleting old toots.
# Prior work
The initial `ephemetoot` script was based on [this tweet-deleting script](https://gist.github.com/flesueur/bcb2d9185b64c5191915d860ad19f23f) by [@flesueur](https://github.com/flesueur)
@ -8,29 +11,29 @@ The initial `ephemetoot` script was based on [this tweet-deleting script](https:
# Usage
You can use `ephemetoot` to delete [Mastodon](https://github.com/tootsuite/mastodon) toots that are older than a certain number of days (default is 365). Toots can optionally be saved from deletion if:
* they are pinned;
* they include certain hashtags;
* they are pinned; or
* they include certain hashtags; or
* they have certain visibility; or
* they are individually listed to be kept
As of version 2, `ephemetoot` can be used for multiple accounts. If you have several 'alts', this can be useful. If you don't have your own server or Mac computer, your friend can now add you to their `ephemetoot` config and it will take care of your old potentially embarrassing toots as well as theirs. However, note [the warning below](#obtain-an-access-token).
As of version 2, `ephemetoot` can be used for multiple accounts. If you have several 'alts', this can be useful. If you don't have your own server or Mac computer, your friend can now add you to their `ephemetoot` config and it will take care of your old toots as well as theirs. However, **note [the warning below](#obtain-an-access-token)**.
# Setup
# Setup & Installation
## Install Python 3
## Install Python 3 and pip
You need to [install Python 3](https://wiki.python.org/moin/BeginnersGuide/Download) to use `ephemetoot`. Python 2 is now end-of-life, however it continued to be installed as the default Python on MacOS until very recently, and may also be installed on your server.
You need to [install Python 3](https://wiki.python.org/moin/BeginnersGuide/Download) to use `ephemetoot`. Python 2 is now end-of-life, however it continued to be installed as the default Python on MacOS and many Linux distributions until very recently, so you should check. You will also need to check that `pip` is installed and pointing to Python3 (not Python2). On some systems this will mean using the command `pip3`.
## Install ephemetoot
### get code with git
### Option 1 - get code with git
If you already have `git` installed on the machine where you're running ephemetoot, you can download the latest release with:
```shell
git clone https://github.com/hughrun/ephemetoot.git
cd ephemetoot
git checkout [tagname]
```
### get code by downloading zip file
If you don't have `git` or don't want to use it, you can download the zip file by clicking the green `Clone or download` button above and selecting `Download ZIP`. You will then need to unzip the file into a new directory where you want to run it.
### Option 2 - get the code by downloading the zip file
If you don't have `git` or don't want to use it, you can download the zip file by clicking the green button above and selecting `Download ZIP`. You will then need to unzip the file into a new directory where you want to run it.
### install using pip
From a command line, move into the main `ephemetoot` directory (i.e. where the README file is) and run:
@ -45,7 +48,7 @@ If you do not have permission to install python modules, you may need to use the
```shell
pip install . --user
```
Note that you will need to run the script with the same user.
Note that you will need to run the script with the same user as ephemetoot will only be installed for that user and not globally.
## Obtain an access token
@ -87,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 | The full toot is archived into individual files named by the Toot's `id` in this writeable directory. |
| archive | A string. The full toot is archived into individual files named by the toot's `id` in this writeable 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:
@ -102,9 +105,18 @@ If you want to use `ephemetoot` for multiple accounts, separate the config for e
# Running the script
It is **strongly recommended** that you do a [test run](#running-in-test-mode) before using `ephemetoot` live.
It is **strongly recommended** that you do a test run before using `ephemetoot` live. There is no "undo"!
To call the script you enter:
## Running in test mode
To do a test-run without actually deleting anything, run the script with the `--test` flag:
```shell
ephemetoot --test
```
## Running in "live" mode
To call the script call ephemetoot with no arguments:
```shell
ephemetoot
```
@ -119,12 +131,6 @@ By default ephemetoot expects there to be a config file called `config.yaml` in
ephemetoot --config '~/directory/subdirectory/config.yaml'
```
## Running in test mode
To do a test-run without actually deleting anything, run the script with the `--test` flag:
```shell
ephemetoot --test
```
## Slow down deletes to match API limit
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.
@ -161,7 +167,7 @@ Deleting old toots daily is the best approach to keeping your timeline clean and
To run automatically every day on a n*x server you could try using crontab:
1. `crontab -e`
2. enter a new line: `@daily ephemetoot --config /path/to/ephemetoot/config.yaml`
2. enter a new line: `@daily /path/to/ephemetoot --config /path/to/ephemetoot/config.yaml`
3. exit with `:qw` (Vi/Vim) or `Ctrl + x` (nano)
### MacOS
@ -204,6 +210,8 @@ Prior to Python 3.7, running a Python script on some BSD and Linux systems may t
* upgrading your Python version to 3.7 or higher. See [Issue 11](https://github.com/hughrun/ephemetoot/issues/11) for more information.
# Upgrading
## Upgrading with git
To upgrade to a new version using git, run the following from inside the `ephemetoot` directory:
```shell
@ -212,7 +220,13 @@ git checkout [tagname]
pip install .
```
Alternatively download and unzip the zip file into your `ephemetoot` directory over the top of your existing installation, and then run `pip install .`.
## Upgrading with a ZIP file
To upgrade without using git:
* put your config file somewhere safe
* download and unzip the zip file into your `ephemetoot` directory over the top of your existing installation
* move your config file back in to the ephemetoot directory
* run `pip install .` from within the directory
# Uninstalling
@ -227,14 +241,10 @@ launchctl unload ~/Library/LaunchAgents/ephemetoot.scheduler.plist
rm ~/Library/LaunchAgents/ephemetoot.scheduler.plist
```
# Bugs and suggestions
Please check existing [issues](https://github.com/hughrun/ephemetoot/issues) and if your issue is not already listed, create a new one with as much detail as possible (but don't include your access token!).
# Contributing
Contributions are very welcome, but if you want to suggest any changes or improvements, please log an issue or have a chat to [me on Mastodon](https://ausglam.space/@hugh) _before_ making a pull request.
For all bugs, suggestions, pull requests or other contributions, please check the [contributing guide](./contributing.md).
# License
GPL 3.0+
This project is [licensed](./LICENSE) under the GPL 3.0 or future version

66
contributing.md Normal file
View File

@ -0,0 +1,66 @@
# Introduction
Thanks for using `ephemetoot`, and for considering contributing to it! Some of the best features have come from suggestions and code contributed by people like you.
You can contribute in many ways - improving the documentation, reporting bugs, suggesting new features, helping test new code, or even writing some code yourself. Following these guidelines will make the process smoother and easier for you and for maintainers and other contributors. That means everyone is happier and improvements get made faster 💫
# Expectations
## Adhere to the Code of Conduct 🤗
All contributors must adhere to the [Code of Conduct](./CODE_OF_CONDUCT.md) for this project. If you do not wish to follow this Code of Conduct, feel free to direct your energies towards a different project.
## Do not log security problems as public issues
If you have identified a security flaw in **ephemetoot**, please email `ephemetoot AT ausglam DOT space` to discuss this confidentially.
## Check existing issues 🧐
Your bug or enhancement might already be listed in the [issues](./issues). It's a good idea to check existing issues before you log your own. If you like someone else's enhancement suggestion, please "upvote" it with a 👍 reaction. If you have also experienced the same bug as someone else, you can add any useful additional context to the existing issue.
## Always log an issue 📝
If you would like to contribute code or documentation changes that do not already have an issue listed, you should always [log an issue](./issues) first. Please **do not add pull requests without prior discussion**. Whilst pull requests are very welcome and encouraged, if you don't log an issue for discussion first, you may end up wasting your time if someone else is already working on the same feature, or maintainers decide it isn't a good fit. This also allows for your proposed feature to be scoped before you get too deep in the weeds coding it.
Regardless of whether is is a bug report, feature request or code proposal, provide as much detail as possible in your issue, and give it a clear name.
## One issue per bug or suggestion ☝️
Each issue should refer to a single bug or enhancement. Don't include multiple suggestions, or a mix of bug report and enhancement proposal, in a single issue. Multiple items in the one issue ticket will make it confusing to know when to close an issue, and means that maintainers will probably have to create new issues so that each task can be tracked properly. It also makes it hard to maintain a clear discussion thread in the issue if there are multiple things being discussed.
## Issue and commit naming conventions ✏️
**Issues** should have clear names that describe the problem or the proposed enhancement. Past examples of good issue titles are:
- "Ephemetoot may die when encountering utf8 encoded toots" ([bug](https://github.com/hughrun/ephemetoot/issues/11))
- "Optionally include datetime stamp with every action" ([enhancement](https://github.com/hughrun/ephemetoot/issues/23))
**Commit and pull request messages** should start with an [imperative verb](https://www.grammarly.com/blog/imperative-verbs/). Simple commits such as documentation fixes may only need a brief sentence. Something bigger like an enhancement should usually have a heading briefly describing the outcome of the commit, with a longer explanation underneath. Past examples of good commit titles are:
- "handle IndexError when there are no toots in the timeline" ([bugfix](https://github.com/hughrun/ephemetoot/commit/92643271d53e00089a10bacd1795cfd50e030413))
- "add support for archiving toots into JSON files" ([new feature](https://github.com/hughrun/ephemetoot/commit/c0d680258ff0fe141fbabcf14a60eee8994e8d18))
## Closing issues in pull requests 🏁
When your pull request resolves an issue, you can optionally use [one of the magic words](https://docs.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword) to automatically close the issue. An example of a longer commit messages that does this is [`Add --version flag`](https://github.com/hughrun/ephemetoot/commit/a1db933bbd6c03e633975463801e6c94f7b9e9fa). The pull request template includes wording for this so you just need to add the issue number.
## Use 'black' code formatting standards 🖤
We use [black](https://pypi.org/project/black/) to maintain code formatting consistency. Thanks to [@MarkEEaton](https://github.com/MarkEEaton) for the suggestion. You should generally run `black .` in the main **ephemetoot** directory before making a pull request, or alternatively check that your code is formatted to the `black` standards. Maintainer [@hughrun](https://github.com/hughrun) often forgets to run `black` so logging an issue about code formatting is completely legitimate 😀
## prefer configuration over flags ⚙️
When adding a new feature, you should probably use a new, _optional_ value in the configuration file, rather than a new command line flag. As a general rule of thumb, use a flag when your change will affect the _output_, and a config value when it will affect the _actions_.
For example, we use a configuration file boolean value for `keep_pinned` because that affects the _actions_ - if it is set to "true" then pinned toots are not deleted, and if set to "false", pinned toots _are_ deleted. On the other hand we use the `--datestamp` flag to print a datestamp against each action as it is logged. This doesn't change the action, merely the output to the screen or log file.
There are some exceptions to this general rule (`--test` prevents any real actions, for example), but the exceptions should be rare and reasonably obvious.
# Your first contribution
First time contributors are warmly encouraged! If you have never contributed to a project on GitHub or another public code repository, the **ephemetoot** maintainers can help you through the process.
## Terminology 📙
You can contribute in many ways - even pointing out where the documentation is unclear will be a real help to future users. Already confused by some of the terms here? Check out [First Timers Only](https://www.firsttimersonly.com) for some tips.
## Pull Requests 🤯
"Pull Requests" can be confusing. You can learn how the process works from this free series [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github).
This is a pretty small project so there usually won't be a lot of issues waiting for someone to work on, but keep an eye out for anything tagged `good first issue` - these are especially for you!
# Help
You can get in touch with Hugh at [@hugh@ausglam.space](https://ausglam.space/@hugh) if you need help contributing or want to discuss something about **ephemetoot**.

View File

@ -1,11 +1,11 @@
# access_token : the access token from the app you created in Mastodon at Settings - Development
# username : your username without the '@' or server domain.
# base_url : the base url of your Mastodon server, without the 'https://'
# username : your username without the "@" or server domain.
# base_url : the base url of your Mastodon server, without the "https://"
# days_to_keep : number of days to keep toots. Defaults to 365
# keep_pinned : either true or false - if true, any pinned toots will be kept (default false)
# toots_to_keep : a list of toot ids indicating toots to be kept regardless of other settings
# hashtags_to_keep : a list of hashtags, where any toots with any of these hashtags will be kept. Do not include the '#' symbol
# visibility_to_keep : any toots with visibility settings in this list will be kept. Options are: 'public', 'unlisted', 'private', 'direct'
# hashtags_to_keep : a list of hashtags, where any toots with any of these hashtags will be kept. Do not include the "#" symbol
# visibility_to_keep : any toots with visibility settings in this list will be kept. Options are: "public", "unlisted", "private", "direct"
# archive : path to a writeable directory into which toots are "archived" as JSON files
# you can list only one user, or multiple users
@ -27,6 +27,7 @@
visibility_to_keep :
- direct
- private
archive : ~/toots_archive/
-
# aus.social account
# values other than access_token, username, and base_url are all optional

View File

@ -1,27 +1,37 @@
from datetime import date, datetime, timedelta, timezone
import json
from mastodon import Mastodon, MastodonError, MastodonAPIError, MastodonNetworkError, MastodonRatelimitError
from mastodon import (
Mastodon,
MastodonError,
MastodonAPIError,
MastodonNetworkError,
MastodonRatelimitError,
)
import os
import requests
import subprocess
import sys
import time
def version(vnum):
try:
latest = requests.get('https://api.github.com/repos/hughrun/ephemetoot/releases/latest')
latest = requests.get(
"https://api.github.com/repos/hughrun/ephemetoot/releases/latest"
)
res = latest.json()
latest_version = res['name']
print('\nYou are using ephemetoot Version ' + vnum)
print('The latest release is ' + latest_version + '\n')
latest_version = res["name"]
print("\nYou are using ephemetoot Version " + vnum)
print("The latest release is " + latest_version + "\n")
except Exception as e:
print('Something went wrong:')
print("Something went wrong:")
print(e)
def schedule(options):
try:
with open(options.schedule + '/ephemetoot.scheduler.plist', 'r') as file:
with open(options.schedule + "/ephemetoot.scheduler.plist", "r") as file:
lines = file.readlines()
if options.schedule == ".":
@ -38,45 +48,55 @@ def schedule(options):
lines[21] = " <integer>" + options.time[0] + "</integer>\n"
lines[23] = " <integer>" + options.time[1] + "</integer>\n"
with open('ephemetoot.scheduler.plist', 'w') as file:
with open("ephemetoot.scheduler.plist", "w") as file:
file.writelines(lines)
sys.tracebacklimit = 0 # suppress Tracebacks
sys.tracebacklimit = 0 # suppress Tracebacks
# save the plist file into ~/Library/LaunchAgents
subprocess.run(
["cp " + options.schedule + "/ephemetoot.scheduler.plist" + " ~/Library/LaunchAgents/"],
shell=True
[
"cp "
+ options.schedule
+ "/ephemetoot.scheduler.plist"
+ " ~/Library/LaunchAgents/"
],
shell=True,
)
# unload any existing file (i.e. if this is an update to the file) and suppress any errors
subprocess.run(
["launchctl unload ~/Library/LaunchAgents/ephemetoot.scheduler.plist"],
stdout=subprocess.DEVNULL,
["launchctl unload ~/Library/LaunchAgents/ephemetoot.scheduler.plist"],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
shell=True
shell=True,
)
# load the new file and suppress any errors
subprocess.run(
["launchctl load ~/Library/LaunchAgents/ephemetoot.scheduler.plist"],
shell=True
shell=True,
)
print('⏰ Scheduled!')
print("⏰ Scheduled!")
except Exception:
print('🙁 Scheduling failed.')
print("🙁 Scheduling failed.")
def checkToots(config, options, retry_count=0):
keep_pinned = 'keep_pinned' in config and config['keep_pinned']
toots_to_keep = config['toots_to_keep'] if 'toots_to_keep' in config else []
visibility_to_keep = config['visibility_to_keep'] if 'visibility_to_keep' in config else []
hashtags_to_keep = set(config['hashtags_to_keep']) if 'hashtags_to_keep' in config else set()
days_to_keep = config['days_to_keep'] if 'days_to_keep' in config else 365
keep_pinned = "keep_pinned" in config and config["keep_pinned"]
toots_to_keep = config["toots_to_keep"] if "toots_to_keep" in config else []
visibility_to_keep = (
config["visibility_to_keep"] if "visibility_to_keep" in config else []
)
hashtags_to_keep = (
set(config["hashtags_to_keep"]) if "hashtags_to_keep" in config else set()
)
days_to_keep = config["days_to_keep"] if "days_to_keep" in config else 365
try:
print(
"Fetching account details for @"
+ config['username']
+ "@"
+ config['base_url']
"Fetching account details for @"
+ config["username"]
+ "@"
+ config["base_url"]
)
def jsondefault(obj):
@ -85,8 +105,10 @@ 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')
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()
@ -97,45 +119,71 @@ def checkToots(config, options, retry_count=0):
if keep_pinned and hasattr(toot, "pinned") and toot.pinned:
if not options.hide_skipped:
if options.datestamp:
print(str( datetime.now(timezone.utc).strftime('%a %d %b %Y %H:%M:%S %z') ), end=' : ')
print(
str(
datetime.now(timezone.utc).strftime(
"%a %d %b %Y %H:%M:%S %z"
)
),
end=" : ",
)
print(
"📌 skipping pinned toot - "
+ str(toot.id)
)
print("📌 skipping pinned toot - " + str(toot.id))
elif toot.id in toots_to_keep:
if not options.hide_skipped:
if options.datestamp:
print(str( datetime.now(timezone.utc).strftime('%a %d %b %Y %H:%M:%S %z') ), end=' : ')
print(
"💾 skipping saved toot - "
+ str(toot.id)
)
print(
str(
datetime.now(timezone.utc).strftime(
"%a %d %b %Y %H:%M:%S %z"
)
),
end=" : ",
)
print("💾 skipping saved toot - " + str(toot.id))
elif toot.visibility in visibility_to_keep:
if not options.hide_skipped:
if options.datestamp:
print(str( datetime.now(timezone.utc).strftime('%a %d %b %Y %H:%M:%S %z') ), end=' : ')
print(
str(
datetime.now(timezone.utc).strftime(
"%a %d %b %Y %H:%M:%S %z"
)
),
end=" : ",
)
print(
"👀 skipping "
+ toot.visibility
+ " toot - "
"👀 skipping "
+ toot.visibility
+ " toot - "
+ str(toot.id)
)
elif len(hashtags_to_keep.intersection(toot_tags)) > 0:
if not options.hide_skipped:
if options.datestamp:
print(str( datetime.now(timezone.utc).strftime('%a %d %b %Y %H:%M:%S %z') ), end=' : ')
print(
"#️⃣ skipping toot with hashtag - "
+ str(toot.id)
)
print(
str(
datetime.now(timezone.utc).strftime(
"%a %d %b %Y %H:%M:%S %z"
)
),
end=" : ",
)
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=' : ')
print(
str(
datetime.now(timezone.utc).strftime(
"%a %d %b %Y %H:%M:%S %z"
)
),
end=" : ",
)
print(
"👎 unboosting toot "
@ -153,7 +201,14 @@ def checkToots(config, options, retry_count=0):
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=' : ')
print(
str(
datetime.now(timezone.utc).strftime(
"%a %d %b %Y %H:%M:%S %z"
)
),
end=" : ",
)
print(
"❌ deleting toot "
@ -172,11 +227,15 @@ def checkToots(config, options, retry_count=0):
diff = mastodon.ratelimit_reset - now
print(
"\nRate limit reached at " +
str( datetime.now(timezone.utc).strftime('%a %d %b %Y %H:%M:%S %z') ) +
' - next reset due in ' +
str(format(diff / 60, '.0f')) +
' minutes.\n'
"\nRate limit reached at "
+ str(
datetime.now(timezone.utc).strftime(
"%a %d %b %Y %H:%M:%S %z"
)
)
+ " - next reset due in "
+ str(format(diff / 60, ".0f"))
+ " minutes.\n"
)
mastodon.status_delete(toot)
@ -187,21 +246,22 @@ def checkToots(config, options, retry_count=0):
diff = mastodon.ratelimit_reset - now
print(
"\nRate limit reached at " +
str( datetime.now(timezone.utc).strftime('%a %d %b %Y %H:%M:%S %z') ) +
' - waiting for next reset due in ' +
str(format(diff / 60, '.0f')) +
' minutes.\n'
"\nRate limit reached at "
+ str(
datetime.now(timezone.utc).strftime(
"%a %d %b %Y %H:%M:%S %z"
)
)
+ " - waiting for next reset due in "
+ str(format(diff / 60, ".0f"))
+ " minutes.\n"
)
time.sleep(diff + 1) # wait for rate limit to reset
time.sleep(diff + 1) # wait for rate limit to reset
except MastodonError as e:
print(
"🛑 ERROR deleting toot - "
+ str(toot.id)
+ " - "
+ str(e.args)
"🛑 ERROR deleting toot - " + str(toot.id) + " - " + str(e.args)
)
print("Waiting 1 minute before re-trying")
time.sleep(60)
@ -212,10 +272,7 @@ def checkToots(config, options, retry_count=0):
2
) # wait 2 secs between deletes to be a bit nicer to the server
except Exception as e:
print(
"🛑 ERROR deleting toot - "
+ str(toot.id)
)
print("🛑 ERROR deleting toot - " + str(toot.id))
print(e)
print("Exiting due to error.")
break
@ -224,24 +281,17 @@ def checkToots(config, options, retry_count=0):
break
except KeyError as e:
print(
"⚠️ There is an error in your config.yaml file. Please add a value for "
+ str(e)
"⚠️ There is an error in your config.yaml file. Please add a value for "
+ str(e)
+ " and try again."
)
break
except:
e = sys.exc_info()
print(
"🛑 Unknown ERROR deleting toot - "
+ str(toot.id)
)
print("ERROR: "
+ str(e[0])
+ " - "
+ str(e[1])
)
print("🛑 Unknown ERROR deleting toot - " + str(toot.id))
print("ERROR: " + str(e[0]) + " - " + str(e[1]))
# the account_statuses call is paginated with a 40-toot limit
# get the id of the last toot to include as 'max_id' in the next API call.
@ -254,7 +304,15 @@ def checkToots(config, options, retry_count=0):
else:
if options.test:
if options.datestamp:
print('\n\n' + str( datetime.now(timezone.utc).strftime('%a %d %b %Y %H:%M:%S %z') ), end=' : ')
print(
"\n\n"
+ str(
datetime.now(timezone.utc).strftime(
"%a %d %b %Y %H:%M:%S %z"
)
),
end=" : ",
)
print(
"Test run completed. This would have removed "
@ -263,34 +321,38 @@ def checkToots(config, options, retry_count=0):
)
else:
if options.datestamp:
print('\n\n' + str( datetime.now(timezone.utc).strftime('%a %d %b %Y %H:%M:%S %z') ), end=' : ')
print(
"\n\n"
+ str(
datetime.now(timezone.utc).strftime(
"%a %d %b %Y %H:%M:%S %z"
)
),
end=" : ",
)
print(
"Removed "
+ str(deleted_count)
+ " toots."
)
print("Removed " + str(deleted_count) + " toots.")
print('')
print('---------------------------------------')
print('🥳 ==> 🧼 ==> 😇 User cleanup complete!')
print('---------------------------------------\n')
print("")
print("---------------------------------------")
print("🥳 ==> 🧼 ==> 😇 User cleanup complete!")
print("---------------------------------------\n")
except IndexError:
print("No toots found!")
if options.pace:
mastodon = Mastodon(
access_token=config['access_token'],
api_base_url="https://" + config['base_url'],
access_token=config["access_token"],
api_base_url="https://" + config["base_url"],
ratelimit_method="pace",
)
else:
mastodon = Mastodon(
access_token=config['access_token'],
api_base_url="https://" + config['base_url'],
access_token=config["access_token"],
api_base_url="https://" + config["base_url"],
ratelimit_method="wait",
)
@ -299,31 +361,23 @@ 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"
)
print("Checking " + str(account.statuses_count) + " toots")
checkBatch(timeline)
except KeyError as val:
print('\n⚠️ error with in your config.yaml file!')
print(
'Please ensure there is a value for '
+ str(val)
+ '\n'
)
print("\n⚠️ error with in your config.yaml file!")
print("Please ensure there is a value for " + str(val) + "\n")
except MastodonAPIError:
print('\n🙅 User and/or access token does not exist or has been deleted')
print("\n🙅 User and/or access token does not exist or has been deleted")
except MastodonNetworkError:
print('\n📡 ephemetoot cannot connect to the server - are you online?')
print("\n📡 ephemetoot cannot connect to the server - are you online?")
if retry_count < 4:
print('Waiting 1 minute before trying again')
print("Waiting 1 minute before trying again")
time.sleep(60)
retry_count += 1
print( 'Attempt ' + str(retry_count + 1) )
print("Attempt " + str(retry_count + 1))
checkToots(config, options, retry_count)
else:
print('Gave up waiting for network')
print("Gave up waiting for network")

View File

@ -1,19 +1,20 @@
from setuptools import setup, find_packages
setup(name='ephemetoot',
version='2.3.1',
url='https://github.com/hughrun/ephemetoot',
license='GPL-3.0-or-later',
packages=find_packages(),
scripts=['bin/ephemetoot'],
install_requires=['Mastodon.py', 'pyyaml', 'requests'],
zip_safe=False,
author='Hugh Rundle',
author_email='hugh@hughrundle.net',
description='A command line tool for selectively deleting old toots from one or more Mastodon accounts.',
keywords='mastodon, mastodon api',
project_urls={
'Source Code': 'https://github.com/hughrun/ephemetoot',
'Documentation': 'https://github.com/hughrun/ephemetoot'
}
)
setup(
name="ephemetoot",
version="2.3.1",
url="https://github.com/hughrun/ephemetoot",
license="GPL-3.0-or-later",
packages=find_packages(),
scripts=["bin/ephemetoot"],
install_requires=["Mastodon.py", "pyyaml", "requests"],
zip_safe=False,
author="Hugh Rundle",
author_email="hugh@hughrundle.net",
description="A command line tool for selectively deleting old toots from one or more Mastodon accounts.",
keywords="mastodon, mastodon api",
project_urls={
"Source Code": "https://github.com/hughrun/ephemetoot",
"Documentation": "https://github.com/hughrun/ephemetoot",
},
)