reconfigure file structure and add toml for poetry

This commit is contained in:
Hugh Rundle 2020-08-26 21:59:01 +10:00
parent 0e1337b926
commit 490dad3bb8
8 changed files with 740 additions and 101 deletions

5
.gitignore vendored
View File

@ -1,3 +1,4 @@
config.py
config.yaml
_assets
_assets
pypi-readme.md
dist

View File

@ -1,66 +0,0 @@
# 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,8 +1,8 @@
#!/usr/bin/env python3
# #####################################################################
# Ephemetoot - A script to delete your old toots
# Copyright (C) 2018 Hugh Rundle, 2019-2020 Hugh Rundle & Mark Eaton
# Ephemetoot - A command line tool to delete your old toots
# Copyright (C) 2018 Hugh Rundle, 2019-2020 Hugh Rundle & others
# Initial work based on tweet-deleting script by @flesueur
# (https://gist.github.com/flesueur/bcb2d9185b64c5191915d860ad19f23f)
#
@ -19,8 +19,8 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# You can contact Hugh on Mastodon @hugh@ausglam.space
# or email hugh [at] hughrundle [dot] net
# You can contact Hugh on Mastodon: @hugh@ausglam.space
# or email: ephemetoot@hugh.run
# #####################################################################
# import
@ -32,10 +32,10 @@ from datetime import datetime, timezone
import os
import pkg_resources
# local files
from lib import ephemetoot
# import funtions
from ephemetoot import ephemetoot as func
# version number from setup.py
# version number from package info
vnum = pkg_resources.require("ephemetoot")[0].version
parser = ArgumentParser()
@ -81,11 +81,11 @@ elif options.config[0] == '/':
else:
config_file = os.path.join( os.getcwd(), options.config )
if __name__ == "__main__":
def main():
if options.version:
ephemetoot.version(vnum)
func.version(vnum)
elif options.schedule:
ephemetoot.schedule(options)
func.schedule(options)
else:
if not options.quiet:
print('')
@ -98,4 +98,7 @@ if __name__ == "__main__":
with open(config_file) as config:
for accounts in yaml.safe_load_all(config):
for user in accounts:
ephemetoot.checkToots(user, options)
func.checkToots(user, options)
if __name__ == '__main__':
main()

476
ephemetoot/ephemetoot.py Normal file
View File

@ -0,0 +1,476 @@
from datetime import date, datetime, timedelta, timezone
import json
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"
)
res = latest.json()
latest_version = res["name"]
print("\nephemetoot ==> 🥳 ==> 🧼 ==> 😇")
print("-------------------------------")
print("You are using \033[92mVersion " + vnum + "\033[0m")
print("Latest release: \033[92m" + latest_version + "\033[0m\n")
except Exception as e:
print("Something went wrong:")
print(e)
def schedule(options):
try:
with open(options.schedule + "/ephemetoot.scheduler.plist", "r") as file:
lines = file.readlines()
if options.schedule == ".":
working_dir = os.getcwd()
else:
working_dir = options.schedule
lines[7] = " <string>" + working_dir + "</string>\n"
lines[10] = " <string>" + sys.argv[0] + "</string>\n"
lines[12] = " <string>" + working_dir + "/config.yaml</string>\n"
if options.time:
lines[21] = " <integer>" + options.time[0] + "</integer>\n"
lines[23] = " <integer>" + options.time[1] + "</integer>\n"
with open("ephemetoot.scheduler.plist", "w") as file:
file.writelines(lines)
sys.tracebacklimit = 0 # suppress Tracebacks
# save the plist file into ~/Library/LaunchAgents
subprocess.run(
[
"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,
stderr=subprocess.DEVNULL,
shell=True,
)
# load the new file and suppress any errors
subprocess.run(
["launchctl load ~/Library/LaunchAgents/ephemetoot.scheduler.plist"],
shell=True,
)
print("⏰ Scheduled!")
except Exception:
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
try:
print(
"Fetching account details for @"
+ config["username"]
+ "@"
+ config["base_url"]
)
def jsondefault(obj):
if isinstance(obj, (date, datetime)):
return obj.isoformat()
def checkBatch(timeline, deleted_count=0):
for toot in timeline:
if "id" in toot and "archive" in config:
# 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 or options.quiet):
if options.datestamp:
print(
str(
datetime.now(timezone.utc).strftime(
"%a %d %b %Y %H:%M:%S %z"
)
),
end=" : ",
)
print("📌 skipping pinned toot - " + str(toot.id))
elif toot.id in toots_to_keep:
if not (options.hide_skipped or options.quiet):
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))
elif toot.visibility in visibility_to_keep:
if not (options.hide_skipped or options.quiet):
if options.datestamp:
print(
str(
datetime.now(timezone.utc).strftime(
"%a %d %b %Y %H:%M:%S %z"
)
),
end=" : ",
)
print(
"👀 skipping "
+ toot.visibility
+ " toot - "
+ str(toot.id)
)
elif len(hashtags_to_keep.intersection(toot_tags)) > 0:
if not (options.hide_skipped or options.quiet):
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))
elif cutoff_date > toot.created_at:
if hasattr(toot, "reblog") and toot.reblog:
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")
)
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:
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 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")
)
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
and not options.quiet
):
now = time.time()
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"
)
# 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)
except MastodonRatelimitError:
now = time.time()
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"
)
time.sleep(diff + 1) # wait for rate limit to reset
except MastodonError as e:
def retry_on_error(attempts):
if attempts < 6:
try:
if not options.quiet:
print(
"Attempt "
+ str(attempts)
+ " at "
+ str(
datetime.now(timezone.utc).strftime(
"%a %d %b %Y %H:%M:%S %z"
)
)
)
mastodon.status_delete(toot)
time.sleep(
2
) # wait 2 secs between deletes to be a bit nicer to the server
except:
attempts += 1
time.sleep(60 * options.retry_mins)
retry_on_error(attempts)
else:
raise TimeoutError("Gave up after 5 attempts")
print(
"🛑 ERROR deleting toot - "
+ str(toot.id)
+ " - "
+ str(e.args[0])
+ " - "
+ str(e.args[3])
)
if not options.quiet:
print(
"Waiting "
+ str(options.retry_mins)
+ " minutes before re-trying"
)
time.sleep(60 * options.retry_mins)
retry_on_error(attempts=2)
except KeyboardInterrupt:
print("Operation aborted.")
break
except KeyError as e:
print(
"⚠️ 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]))
# 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.
# then keep triggering new rounds of checkToots() until there are no more toots to check
try:
max_id = timeline[-1:][0].id
next_batch = mastodon.account_statuses(user_id, limit=40, max_id=max_id)
if len(next_batch) > 0:
checkBatch(next_batch, deleted_count)
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(
"Test run completed. This would have removed "
+ str(deleted_count)
+ " toots."
)
else:
if options.datestamp:
print(
"\n\n"
+ str(
datetime.now(timezone.utc).strftime(
"%a %d %b %Y %H:%M:%S %z"
)
),
end=" : ",
)
print("Removed " + str(deleted_count) + " toots.")
if not options.quiet:
print("\n---------------------------------------")
print("🥳 ==> 🧼 ==> 😇 User cleanup complete!")
print("---------------------------------------\n")
except IndexError:
print("No toots found!")
except Exception as e:
print("ERROR: " + str(e.args[0]))
if options.pace:
mastodon = Mastodon(
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"],
ratelimit_method="wait",
)
# STARTS HERE
cutoff_date = datetime.now(timezone.utc) - timedelta(days=days_to_keep)
user_id = mastodon.account_verify_credentials().id
account = mastodon.account(user_id)
timeline = mastodon.account_statuses(user_id, limit=40)
if not options.quiet:
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")
except MastodonAPIError as e:
if e.args[1] == 401:
print("\n🙅 User and/or access token does not exist or has been deleted (401)")
elif e.args[1] == 404:
print("\n🔭 Can't find that server (404)")
else:
print("\n😕 Server has returned an error (5xx)")
except MastodonNetworkError:
if retry_count == 0:
print("\n📡 ephemetoot cannot connect to the server - are you online?")
if retry_count < 4:
print(
"Waiting "
+ str(options.retry_mins)
+ " minutes before trying again"
)
time.sleep(60 * options.retry_mins)
retry_count += 1
print("Attempt " + str(retry_count + 1))
checkToots(config, options, retry_count)
else:
print("Gave up waiting for network")

View File

@ -13,6 +13,8 @@ import subprocess
import sys
import time
def config():
# TODO: this function should run through the config options and then create a config file
def version(vnum):
try:
@ -21,8 +23,10 @@ def version(vnum):
)
res = latest.json()
latest_version = res["name"]
print("\nYou are using ephemetoot Version " + vnum)
print("The latest release is " + latest_version + "\n")
print("\nephemetoot ==> 🥳 ==> 🧼 ==> 😇")
print("-------------------------------")
print("You are using \033[92mVersion " + vnum + "\033[0m")
print("Latest release: \033[92m" + latest_version + "\033[0m\n")
except Exception as e:
print("Something went wrong:")
@ -30,6 +34,7 @@ def version(vnum):
def schedule(options):
# TODO: change this so it just writes out the entire file from here direct to the ~/Library
try:
with open(options.schedule + "/ephemetoot.scheduler.plist", "r") as file:
lines = file.readlines()

206
poetry.lock generated Normal file
View File

@ -0,0 +1,206 @@
[[package]]
category = "main"
description = "Pure-Python implementation of the blurhash algorithm."
name = "blurhash"
optional = false
python-versions = "*"
version = "1.1.4"
[package.extras]
test = ["pillow", "numpy", "pytest"]
[[package]]
category = "main"
description = "Python package for providing Mozilla's CA Bundle."
name = "certifi"
optional = false
python-versions = "*"
version = "2020.6.20"
[[package]]
category = "main"
description = "Universal encoding detector for Python 2 and 3"
name = "chardet"
optional = false
python-versions = "*"
version = "3.0.4"
[[package]]
category = "main"
description = "Decorators for Humans"
name = "decorator"
optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*"
version = "4.4.2"
[[package]]
category = "main"
description = "Internationalized Domain Names in Applications (IDNA)"
name = "idna"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "2.10"
[[package]]
category = "main"
description = "Python wrapper for the Mastodon API"
name = "mastodon.py"
optional = false
python-versions = "*"
version = "1.5.1"
[package.dependencies]
blurhash = ">=1.1.4"
decorator = ">=4.0.0"
python-dateutil = "*"
python-magic = "*"
pytz = "*"
requests = ">=2.4.2"
six = "*"
[package.extras]
blurhash = ["blurhash (>=1.1.4)"]
test = ["blurhash (>=1.1.4)", "cryptography (>=1.6.0)", "http-ece (>=1.0.5)", "pytest", "pytest-cov", "pytest-mock", "pytest-runner", "pytest-vcr", "requests-mock", "vcrpy"]
webpush = ["cryptography (>=1.6.0)", "http-ece (>=1.0.5)"]
[[package]]
category = "main"
description = "Extensions to the standard Python datetime module"
name = "python-dateutil"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
version = "2.8.1"
[package.dependencies]
six = ">=1.5"
[[package]]
category = "main"
description = "File type identification using libmagic"
name = "python-magic"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
version = "0.4.18"
[[package]]
category = "main"
description = "World timezone definitions, modern and historical"
name = "pytz"
optional = false
python-versions = "*"
version = "2020.1"
[[package]]
category = "main"
description = "YAML parser and emitter for Python"
name = "pyyaml"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
version = "5.3.1"
[[package]]
category = "main"
description = "Python HTTP for Humans."
name = "requests"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
version = "2.24.0"
[package.dependencies]
certifi = ">=2017.4.17"
chardet = ">=3.0.2,<4"
idna = ">=2.5,<3"
urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26"
[package.extras]
security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"]
socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"]
[[package]]
category = "main"
description = "Python 2 and 3 compatibility utilities"
name = "six"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
version = "1.15.0"
[[package]]
category = "main"
description = "HTTP library with thread-safe connection pooling, file post, and more."
name = "urllib3"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4"
version = "1.25.10"
[package.extras]
brotli = ["brotlipy (>=0.6.0)"]
secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "pyOpenSSL (>=0.14)", "ipaddress"]
socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"]
[metadata]
content-hash = "35d07702bbbc789f7e6dc248539c816144f6b4a294d7f5e277ab4aed3c094584"
lock-version = "1.1"
python-versions = "^3.6"
[metadata.files]
blurhash = [
{file = "blurhash-1.1.4-py2.py3-none-any.whl", hash = "sha256:7611c1bc41383d2349b6129208587b5d61e8792ce953893cb49c38beeb400d1d"},
{file = "blurhash-1.1.4.tar.gz", hash = "sha256:da56b163e5a816e4ad07172f5639287698e09d7f3dc38d18d9726d9c1dbc4cee"},
]
certifi = [
{file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"},
{file = "certifi-2020.6.20.tar.gz", hash = "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3"},
]
chardet = [
{file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"},
{file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"},
]
decorator = [
{file = "decorator-4.4.2-py2.py3-none-any.whl", hash = "sha256:41fa54c2a0cc4ba648be4fd43cff00aedf5b9465c9bf18d64325bc225f08f760"},
{file = "decorator-4.4.2.tar.gz", hash = "sha256:e3a62f0520172440ca0dcc823749319382e377f37f140a0b99ef45fecb84bfe7"},
]
idna = [
{file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"},
{file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"},
]
"mastodon.py" = [
{file = "Mastodon.py-1.5.1-py2.py3-none-any.whl", hash = "sha256:cc454cac0ed1ae4f105f7399ea53f5b31a1be5075d1882f47162d2e78a9e4064"},
{file = "Mastodon.py-1.5.1.tar.gz", hash = "sha256:2afddbad8b5d7326fcc8a8f8c62bfe956e34627f516b06c6694fc8c8fedc33ee"},
]
python-dateutil = [
{file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"},
{file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"},
]
python-magic = [
{file = "python-magic-0.4.18.tar.gz", hash = "sha256:b757db2a5289ea3f1ced9e60f072965243ea43a2221430048fd8cacab17be0ce"},
{file = "python_magic-0.4.18-py2.py3-none-any.whl", hash = "sha256:356efa93c8899047d1eb7d3eb91e871ba2f5b1376edbaf4cc305e3c872207355"},
]
pytz = [
{file = "pytz-2020.1-py2.py3-none-any.whl", hash = "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed"},
{file = "pytz-2020.1.tar.gz", hash = "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048"},
]
pyyaml = [
{file = "PyYAML-5.3.1-cp27-cp27m-win32.whl", hash = "sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f"},
{file = "PyYAML-5.3.1-cp27-cp27m-win_amd64.whl", hash = "sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76"},
{file = "PyYAML-5.3.1-cp35-cp35m-win32.whl", hash = "sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2"},
{file = "PyYAML-5.3.1-cp35-cp35m-win_amd64.whl", hash = "sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c"},
{file = "PyYAML-5.3.1-cp36-cp36m-win32.whl", hash = "sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2"},
{file = "PyYAML-5.3.1-cp36-cp36m-win_amd64.whl", hash = "sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648"},
{file = "PyYAML-5.3.1-cp37-cp37m-win32.whl", hash = "sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a"},
{file = "PyYAML-5.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf"},
{file = "PyYAML-5.3.1-cp38-cp38-win32.whl", hash = "sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97"},
{file = "PyYAML-5.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee"},
{file = "PyYAML-5.3.1.tar.gz", hash = "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d"},
]
requests = [
{file = "requests-2.24.0-py2.py3-none-any.whl", hash = "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"},
{file = "requests-2.24.0.tar.gz", hash = "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b"},
]
six = [
{file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"},
{file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"},
]
urllib3 = [
{file = "urllib3-1.25.10-py2.py3-none-any.whl", hash = "sha256:e7983572181f5e1522d9c98453462384ee92a0be7fac5f1413a1e35c56cc0461"},
{file = "urllib3-1.25.10.tar.gz", hash = "sha256:91056c15fa70756691db97756772bb1eb9678fa585d9184f24534b100dc60f4a"},
]

34
pyproject.toml Normal file
View File

@ -0,0 +1,34 @@
[tool.poetry]
name = "ephemetoot"
version = "2.6.2"
description = "A command line tool to delete your old toots"
authors = ["Hugh Rundle <ephemetoot@hugh.run>"]
license = "OSI Approved :: GNU General Public License v3 or later (GPLv3+)"
readme = "pypi-readme.md"
homepage = "https://ephemetoot.hugh.run"
repository = "https://github.com/hughrun/ephemetoot"
keywords = ["mastodon", "api", "microblogging"]
classifiers = [
"Environment :: Console",
"Operating System :: OS Independent",
"Topic :: Communications"
]
include = [
"LICENSE",
]
[tool.poetry.dependencies]
python = "^3.6"
requests = "^2.22.0"
"mastodon.py" = "^1.4.3"
pyyaml = "^5.0"
[tool.poetry.dev-dependencies]
# TODO - tests!
[tool.poetry.scripts]
ephemetoot = 'ephemetoot.console:main'
[build-system]
requires = ["poetry-core>=1.0.0a5"]
build-backend = "poetry.core.masonry.api"

View File

@ -1,20 +0,0 @@
from setuptools import setup, find_packages
setup(
name="ephemetoot",
version="2.6",
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",
},
)