From f9336e23da625c62897f456bf74e46868fafd344 Mon Sep 17 00:00:00 2001 From: sneakers-the-rat Date: Thu, 22 Dec 2022 19:50:36 -0800 Subject: [PATCH] initial just getting started checkpoint --- .env.sample | 3 + paperbot/__init__.py | 1 + paperbot/client.py | 60 +++++++ paperbot/config.py | 0 paperbot/logger.py | 56 +++++++ paperbot/models/__init__.py | 0 paperbot/models/account.py | 42 +++++ paperbot/models/status.py | 58 +++++++ paperbot/patterns/__init__.py | 0 paperbot/patterns/doi.py | 0 poetry.lock | 304 ++++++++++++++++++++++++++++++++++ pyproject.toml | 20 +++ 12 files changed, 544 insertions(+) create mode 100644 .env.sample create mode 100644 paperbot/__init__.py create mode 100644 paperbot/client.py create mode 100644 paperbot/config.py create mode 100644 paperbot/logger.py create mode 100644 paperbot/models/__init__.py create mode 100644 paperbot/models/account.py create mode 100644 paperbot/models/status.py create mode 100644 paperbot/patterns/__init__.py create mode 100644 paperbot/patterns/doi.py create mode 100644 poetry.lock create mode 100644 pyproject.toml diff --git a/.env.sample b/.env.sample new file mode 100644 index 0000000..313c984 --- /dev/null +++ b/.env.sample @@ -0,0 +1,3 @@ +MASTO_URL= +MASTO_TOKEN= +LOGDIR= \ No newline at end of file diff --git a/paperbot/__init__.py b/paperbot/__init__.py new file mode 100644 index 0000000..f7510e3 --- /dev/null +++ b/paperbot/__init__.py @@ -0,0 +1 @@ +from paperbot.config import Config \ No newline at end of file diff --git a/paperbot/client.py b/paperbot/client.py new file mode 100644 index 0000000..6e436e4 --- /dev/null +++ b/paperbot/client.py @@ -0,0 +1,60 @@ +""" +Runtime for the bot :) +""" + +from mastodon import Mastodon, StreamListener + +from paperbot import Config +from paperbot.logger import init_logger + +class UserListener(StreamListener): + def __init__(self, client:Mastodon, config:Config): + self.client = client + self.config = config + self.logger = init_logger(name="user-listener", basedir=config.LOGDIR) + + + def on_update(self, status): + """On status...""" + pass + + def on_notification(self, notif): + pass + + def on_conversation(self, convo): + """On dm...""" + pass + + def on_unknown_event(self, event): + """#TODO: log this..""" + pass + + def follow_back(self, notification): + self.client.account_follow(notification['account']['id']) + self.logger.debug(f'account followed! {notification["account"]["url"]} with id {notification["account"]["id"]}') + +class Paperbot: + def __init__(self, config:Optional[Config]=None, post_length=500): + self._me = None # type: Optional[Account] + + if config is None: + config = Config() + + self.config = config + self.config.LOGDIR.mkdir(exist_ok=True) + self.post_length = post_length + self.logger = init_logger('paperbot', basedir=self.config.LOGDIR) + + self.client = Mastodon( + access_token=self.config.MASTO_TOKEN, + api_base_url=self.config.MASTO_URL + ) + + def init_stream(self, run_async:bool=True): + # Listen to a stream consisting of just us. + listener = UserListener(self.client, self.config) + self.logger.info('Initializing streaming') + self.client.stream_user( + listener = listener, + run_async=run_async + ) \ No newline at end of file diff --git a/paperbot/config.py b/paperbot/config.py new file mode 100644 index 0000000..e69de29 diff --git a/paperbot/logger.py b/paperbot/logger.py new file mode 100644 index 0000000..6d00daf --- /dev/null +++ b/paperbot/logger.py @@ -0,0 +1,56 @@ +import logging +from rich.logging import RichHandler +from pathlib import Path +import sys +import typing +from typing import Optional, Union, Tuple, List, Dict, Literal +from logging.handlers import RotatingFileHandler + +def init_logger( + name:Optional[str]=None, + basedir:Optional[Path]=None, + loglevel:str='DEBUG', + loglevel_disk:Optional[str]='DEBUG' + ): + if name is None: + name = 'paperbot' + else: + if not name.startswith('paperbot'): + name = '.'.join(['paperbot', name]) + + if loglevel_disk is None: + loglevel_disk = loglevel + + logger = logging.getLogger(name) + logger.setLevel(loglevel) + + + if basedir is not None: + logger.addHandler(_file_handler(basedir, name, loglevel_disk)) + + logger.addHandler(_rich_handler()) + return logger + + +def _file_handler(basedir:Path, name:str, loglevel:str="DEBUG") -> RotatingFileHandler: + filename = Path(basedir) / '.'.join([name, 'log']) + basedir.mkdir(parents=True, exist_ok=True) + file_handler = RotatingFileHandler( + str(filename), + mode='a', + maxBytes=2 ** 24, + backupCount=5 + ) + file_formatter = logging.Formatter("[%(asctime)s] %(levelname)s [%(name)s]: %(message)s") + file_handler.setLevel(loglevel) + file_handler.setFormatter(file_formatter) + return file_handler + +def _rich_handler() -> RichHandler: + rich_handler = RichHandler(rich_tracebacks=True, markup=True) + rich_formatter = logging.Formatter( + "[bold green]\[%(name)s][/bold green] %(message)s", + datefmt='[%y-%m-%dT%H:%M:%S]' + ) + rich_handler.setFormatter(rich_formatter) + return rich_handler \ No newline at end of file diff --git a/paperbot/models/__init__.py b/paperbot/models/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/paperbot/models/account.py b/paperbot/models/account.py new file mode 100644 index 0000000..39e7dea --- /dev/null +++ b/paperbot/models/account.py @@ -0,0 +1,42 @@ +from pydantic import BaseModel, AnyHttpUrl +from pydantic import Field as _Field +from datetime import datetime +from typing import Optional, List +from bs4 import BeautifulSoup + +class Field(BaseModel): + name: str + value: str + url: Optional[AnyHttpUrl] = None + + def __init__(self, name:str, value:str): + soup = BeautifulSoup(value, 'lxml') + a = soup.find('a') + if a is not None: + url = a.get('href') + else: + url = None + super().__init__(name=name, value=value, url=url) + + class Config: + extra = "ignore" + + +class Account(BaseModel): + """Not transcribing full model now, just using to check""" + acct: str + avatar: str + avatar_static: str + bot: bool + created_at:datetime + discoverable:bool + display_name:str + fields: List[Field] = _Field(default_factory=list) + followers_count:int + following_count:int + id: int + url: AnyHttpUrl + username: str + + class Config: + extra = 'ignore' \ No newline at end of file diff --git a/paperbot/models/status.py b/paperbot/models/status.py new file mode 100644 index 0000000..ffbee57 --- /dev/null +++ b/paperbot/models/status.py @@ -0,0 +1,58 @@ +from typing import Optional, Literal, List +from datetime import datetime +from pydantic import BaseModel, Field +import re +from bs4 import BeautifulSoup +import pypandoc + +from masto_ld.models.models import Account +from masto_ld.patterns.wikilink import Wikilink + +from typing import TYPE_CHECKING +if TYPE_CHECKING: + from masto_ld.models.thread import Thread + +class Mention(BaseModel): + acct: str + id: int + url: str + username: str + +class Status(BaseModel): + """ + Model of a toot on mastodon + + See: https://mastodonpy.readthedocs.io/en/stable/#toot-dicts + """ + id: int + url: str + account: Account + content: str + created_at: datetime + visibility: Literal['public', 'unlisted', 'private', 'direct'] + in_reply_to_id: Optional[int] = None + in_reply_to_account_id: Optional[int] = None + mentions: Optional[List[Mention]] = None + + def format_content(self, format:str='commonmark-raw_html') -> str: + """Format the HTMl content of the post using pypandoc""" + output = pypandoc.convert_text(self.content, format, format='html') + return output + + @property + def soup(self) -> BeautifulSoup: + return BeautifulSoup(self.content) + + @property + def wikilinks(self) -> List[Wikilink]: + return Wikilink.parse(self.content) + + class Config: + extra='ignore' + +class Post(BaseModel): + #timestamp: Optional[datetime] = None + text:str + status:Optional[Status] = None + + diff --git a/paperbot/patterns/__init__.py b/paperbot/patterns/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/paperbot/patterns/doi.py b/paperbot/patterns/doi.py new file mode 100644 index 0000000..e69de29 diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..f69386d --- /dev/null +++ b/poetry.lock @@ -0,0 +1,304 @@ +[[package]] +name = "blurhash" +version = "1.1.4" +description = "Pure-Python implementation of the blurhash algorithm." +category = "main" +optional = false +python-versions = "*" + +[package.extras] +test = ["Pillow", "numpy", "pytest"] + +[[package]] +name = "certifi" +version = "2022.12.7" +description = "Python package for providing Mozilla's CA Bundle." +category = "main" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "charset-normalizer" +version = "2.1.1" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "main" +optional = false +python-versions = ">=3.6.0" + +[package.extras] +unicode-backport = ["unicodedata2"] + +[[package]] +name = "commonmark" +version = "0.9.1" +description = "Python parser for the CommonMark Markdown spec" +category = "main" +optional = false +python-versions = "*" + +[package.extras] +test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"] + +[[package]] +name = "decorator" +version = "5.1.1" +description = "Decorators for Humans" +category = "main" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "idna" +version = "3.4" +description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "mastodon-py" +version = "1.8.0" +description = "Python wrapper for the Mastodon API" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +blurhash = ">=1.1.4" +decorator = ">=4.0.0" +python-dateutil = "*" +python-magic = "*" +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", "pytz", "requests-mock", "vcrpy"] +webpush = ["cryptography (>=1.6.0)", "http-ece (>=1.0.5)"] + +[[package]] +name = "pydantic" +version = "1.10.2" +description = "Data validation and settings management using python type hints" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +typing-extensions = ">=4.1.0" + +[package.extras] +dotenv = ["python-dotenv (>=0.10.4)"] +email = ["email-validator (>=1.0.3)"] + +[[package]] +name = "pygments" +version = "2.13.0" +description = "Pygments is a syntax highlighting package written in Python." +category = "main" +optional = false +python-versions = ">=3.6" + +[package.extras] +plugins = ["importlib-metadata"] + +[[package]] +name = "pyparsing" +version = "3.0.9" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" +category = "main" +optional = false +python-versions = ">=3.6.8" + +[package.extras] +diagrams = ["jinja2", "railroad-diagrams"] + +[[package]] +name = "python-dateutil" +version = "2.8.2" +description = "Extensions to the standard Python datetime module" +category = "main" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "python-magic" +version = "0.4.27" +description = "File type identification using libmagic" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "requests" +version = "2.28.1" +description = "Python HTTP for Humans." +category = "main" +optional = false +python-versions = ">=3.7, <4" + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<3" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<1.27" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "rich" +version = "12.6.0" +description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +category = "main" +optional = false +python-versions = ">=3.6.3,<4.0.0" + +[package.dependencies] +commonmark = ">=0.9.0,<0.10.0" +pygments = ">=2.6.0,<3.0.0" + +[package.extras] +jupyter = ["ipywidgets (>=7.5.1,<8.0.0)"] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" + +[[package]] +name = "typing-extensions" +version = "4.4.0" +description = "Backported and Experimental Type Hints for Python 3.7+" +category = "main" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "urllib3" +version = "1.26.13" +description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] + +[metadata] +lock-version = "1.1" +python-versions = "^3.9" +content-hash = "a109d5afdedcbf0bff92d36c432c3555501b3dd51c9ea51a2d576ca6bc4f6eaf" + +[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-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, + {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, +] +charset-normalizer = [ + {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"}, + {file = "charset_normalizer-2.1.1-py3-none-any.whl", hash = "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"}, +] +commonmark = [ + {file = "commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"}, + {file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"}, +] +decorator = [ + {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, + {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, +] +idna = [ + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, +] +mastodon-py = [ + {file = "Mastodon.py-1.8.0-py2.py3-none-any.whl", hash = "sha256:31624c881318682577b76c082a9e8e4114a42e80ad3652c6bc00e5c658cea1a7"}, + {file = "Mastodon.py-1.8.0.tar.gz", hash = "sha256:f5af3bb16df6409bed0bb8b97543d7979237a6a2a2a4bc484dec261c36918668"}, +] +pydantic = [ + {file = "pydantic-1.10.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bb6ad4489af1bac6955d38ebcb95079a836af31e4c4f74aba1ca05bb9f6027bd"}, + {file = "pydantic-1.10.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a1f5a63a6dfe19d719b1b6e6106561869d2efaca6167f84f5ab9347887d78b98"}, + {file = "pydantic-1.10.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:352aedb1d71b8b0736c6d56ad2bd34c6982720644b0624462059ab29bd6e5912"}, + {file = "pydantic-1.10.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:19b3b9ccf97af2b7519c42032441a891a5e05c68368f40865a90eb88833c2559"}, + {file = "pydantic-1.10.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e9069e1b01525a96e6ff49e25876d90d5a563bc31c658289a8772ae186552236"}, + {file = "pydantic-1.10.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:355639d9afc76bcb9b0c3000ddcd08472ae75318a6eb67a15866b87e2efa168c"}, + {file = "pydantic-1.10.2-cp310-cp310-win_amd64.whl", hash = "sha256:ae544c47bec47a86bc7d350f965d8b15540e27e5aa4f55170ac6a75e5f73b644"}, + {file = "pydantic-1.10.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a4c805731c33a8db4b6ace45ce440c4ef5336e712508b4d9e1aafa617dc9907f"}, + {file = "pydantic-1.10.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d49f3db871575e0426b12e2f32fdb25e579dea16486a26e5a0474af87cb1ab0a"}, + {file = "pydantic-1.10.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37c90345ec7dd2f1bcef82ce49b6235b40f282b94d3eec47e801baf864d15525"}, + {file = "pydantic-1.10.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b5ba54d026c2bd2cb769d3468885f23f43710f651688e91f5fb1edcf0ee9283"}, + {file = "pydantic-1.10.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:05e00dbebbe810b33c7a7362f231893183bcc4251f3f2ff991c31d5c08240c42"}, + {file = "pydantic-1.10.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2d0567e60eb01bccda3a4df01df677adf6b437958d35c12a3ac3e0f078b0ee52"}, + {file = "pydantic-1.10.2-cp311-cp311-win_amd64.whl", hash = "sha256:c6f981882aea41e021f72779ce2a4e87267458cc4d39ea990729e21ef18f0f8c"}, + {file = "pydantic-1.10.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c4aac8e7103bf598373208f6299fa9a5cfd1fc571f2d40bf1dd1955a63d6eeb5"}, + {file = "pydantic-1.10.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a7b66c3f499108b448f3f004801fcd7d7165fb4200acb03f1c2402da73ce4c"}, + {file = "pydantic-1.10.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bedf309630209e78582ffacda64a21f96f3ed2e51fbf3962d4d488e503420254"}, + {file = "pydantic-1.10.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9300fcbebf85f6339a02c6994b2eb3ff1b9c8c14f502058b5bf349d42447dcf5"}, + {file = "pydantic-1.10.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:216f3bcbf19c726b1cc22b099dd409aa371f55c08800bcea4c44c8f74b73478d"}, + {file = "pydantic-1.10.2-cp37-cp37m-win_amd64.whl", hash = "sha256:dd3f9a40c16daf323cf913593083698caee97df2804aa36c4b3175d5ac1b92a2"}, + {file = "pydantic-1.10.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b97890e56a694486f772d36efd2ba31612739bc6f3caeee50e9e7e3ebd2fdd13"}, + {file = "pydantic-1.10.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9cabf4a7f05a776e7793e72793cd92cc865ea0e83a819f9ae4ecccb1b8aa6116"}, + {file = "pydantic-1.10.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06094d18dd5e6f2bbf93efa54991c3240964bb663b87729ac340eb5014310624"}, + {file = "pydantic-1.10.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cc78cc83110d2f275ec1970e7a831f4e371ee92405332ebfe9860a715f8336e1"}, + {file = "pydantic-1.10.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ee433e274268a4b0c8fde7ad9d58ecba12b069a033ecc4645bb6303c062d2e9"}, + {file = "pydantic-1.10.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7c2abc4393dea97a4ccbb4ec7d8658d4e22c4765b7b9b9445588f16c71ad9965"}, + {file = "pydantic-1.10.2-cp38-cp38-win_amd64.whl", hash = "sha256:0b959f4d8211fc964772b595ebb25f7652da3f22322c007b6fed26846a40685e"}, + {file = "pydantic-1.10.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c33602f93bfb67779f9c507e4d69451664524389546bacfe1bee13cae6dc7488"}, + {file = "pydantic-1.10.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5760e164b807a48a8f25f8aa1a6d857e6ce62e7ec83ea5d5c5a802eac81bad41"}, + {file = "pydantic-1.10.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6eb843dcc411b6a2237a694f5e1d649fc66c6064d02b204a7e9d194dff81eb4b"}, + {file = "pydantic-1.10.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b8795290deaae348c4eba0cebb196e1c6b98bdbe7f50b2d0d9a4a99716342fe"}, + {file = "pydantic-1.10.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e0bedafe4bc165ad0a56ac0bd7695df25c50f76961da29c050712596cf092d6d"}, + {file = "pydantic-1.10.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2e05aed07fa02231dbf03d0adb1be1d79cabb09025dd45aa094aa8b4e7b9dcda"}, + {file = "pydantic-1.10.2-cp39-cp39-win_amd64.whl", hash = "sha256:c1ba1afb396148bbc70e9eaa8c06c1716fdddabaf86e7027c5988bae2a829ab6"}, + {file = "pydantic-1.10.2-py3-none-any.whl", hash = "sha256:1b6ee725bd6e83ec78b1aa32c5b1fa67a3a65badddde3976bca5fe4568f27709"}, + {file = "pydantic-1.10.2.tar.gz", hash = "sha256:91b8e218852ef6007c2b98cd861601c6a09f1aa32bbbb74fab5b1c33d4a1e410"}, +] +pygments = [ + {file = "Pygments-2.13.0-py3-none-any.whl", hash = "sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42"}, + {file = "Pygments-2.13.0.tar.gz", hash = "sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1"}, +] +pyparsing = [ + {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, + {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, +] +python-dateutil = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] +python-magic = [ + {file = "python-magic-0.4.27.tar.gz", hash = "sha256:c1ba14b08e4a5f5c31a302b7721239695b2f0f058d125bd5ce1ee36b9d9d3c3b"}, + {file = "python_magic-0.4.27-py2.py3-none-any.whl", hash = "sha256:c212960ad306f700aa0d01e5d7a325d20548ff97eb9920dcd29513174f0294d3"}, +] +requests = [ + {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"}, + {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, +] +rich = [ + {file = "rich-12.6.0-py3-none-any.whl", hash = "sha256:a4eb26484f2c82589bd9a17c73d32a010b1e29d89f1604cd9bf3a2097b81bb5e"}, + {file = "rich-12.6.0.tar.gz", hash = "sha256:ba3a3775974105c221d31141f2c116f4fd65c5ceb0698657a11e9f295ec93fd0"}, +] +six = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] +typing-extensions = [ + {file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"}, + {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"}, +] +urllib3 = [ + {file = "urllib3-1.26.13-py2.py3-none-any.whl", hash = "sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc"}, + {file = "urllib3-1.26.13.tar.gz", hash = "sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8"}, +] diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..abc3695 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,20 @@ +[tool.poetry] +name = "paperbot" +version = "0.1.0" +description = "A mastodon bot for detecting DOIs in papers and making canonical threads for them." +authors = ["sneakers-the-rat "] +license = "AGPL-3.0-or-later" +readme = "README.md" +packages = [{include = "paper_bot"}] + +[tool.poetry.dependencies] +python = "^3.9" +"Mastodon.py" = "^1.8.0" +pydantic = "^1.10.2" +pyparsing = "^3.0.9" +rich = "^12.6.0" + + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api"