tumblrbot 1.4.0__tar.gz → 1.4.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {tumblrbot-1.4.0 → tumblrbot-1.4.1}/PKG-INFO +3 -1
- {tumblrbot-1.4.0 → tumblrbot-1.4.1}/README.md +2 -0
- {tumblrbot-1.4.0 → tumblrbot-1.4.1}/pyproject.toml +1 -1
- {tumblrbot-1.4.0 → tumblrbot-1.4.1}/src/tumblrbot/__main__.py +1 -1
- {tumblrbot-1.4.0 → tumblrbot-1.4.1}/src/tumblrbot/flow/examples.py +1 -1
- {tumblrbot-1.4.0 → tumblrbot-1.4.1}/src/tumblrbot/utils/models.py +46 -36
- {tumblrbot-1.4.0 → tumblrbot-1.4.1}/src/tumblrbot/utils/tumblr.py +1 -1
- {tumblrbot-1.4.0 → tumblrbot-1.4.1}/.github/dependabot.yml +0 -0
- {tumblrbot-1.4.0 → tumblrbot-1.4.1}/.gitignore +0 -0
- {tumblrbot-1.4.0 → tumblrbot-1.4.1}/UNLICENSE +0 -0
- {tumblrbot-1.4.0 → tumblrbot-1.4.1}/src/tumblrbot/__init__.py +0 -0
- {tumblrbot-1.4.0 → tumblrbot-1.4.1}/src/tumblrbot/flow/__init__.py +0 -0
- {tumblrbot-1.4.0 → tumblrbot-1.4.1}/src/tumblrbot/flow/download.py +0 -0
- {tumblrbot-1.4.0 → tumblrbot-1.4.1}/src/tumblrbot/flow/fine_tune.py +0 -0
- {tumblrbot-1.4.0 → tumblrbot-1.4.1}/src/tumblrbot/flow/generate.py +0 -0
- {tumblrbot-1.4.0 → tumblrbot-1.4.1}/src/tumblrbot/utils/__init__.py +0 -0
- {tumblrbot-1.4.0 → tumblrbot-1.4.1}/src/tumblrbot/utils/common.py +0 -0
- {tumblrbot-1.4.0 → tumblrbot-1.4.1}/src/tumblrbot/utils/config.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tumblrbot
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.1
|
|
4
4
|
Summary: An updated bot that posts to Tumblr, based on your very own blog!
|
|
5
5
|
Requires-Python: >= 3.13
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -73,6 +73,8 @@ Features:
|
|
|
73
73
|
|
|
74
74
|
**To-Do:**
|
|
75
75
|
- Add code documentation.
|
|
76
|
+
- Fix inaccurate post counts when downloading posts.
|
|
77
|
+
- Fix file not found error when starting fine-tuning.
|
|
76
78
|
|
|
77
79
|
|
|
78
80
|
**Please submit an issue or contact us for features you want added/reimplemented.**
|
|
@@ -53,6 +53,8 @@ Features:
|
|
|
53
53
|
|
|
54
54
|
**To-Do:**
|
|
55
55
|
- Add code documentation.
|
|
56
|
+
- Fix inaccurate post counts when downloading posts.
|
|
57
|
+
- Fix file not found error when starting fine-tuning.
|
|
56
58
|
|
|
57
59
|
|
|
58
60
|
**Please submit an issue or contact us for features you want added/reimplemented.**
|
|
@@ -13,7 +13,7 @@ from tumblrbot.utils.tumblr import TumblrClient
|
|
|
13
13
|
def main() -> None:
|
|
14
14
|
install()
|
|
15
15
|
|
|
16
|
-
tokens = Tokens()
|
|
16
|
+
tokens = Tokens.read_from_keyring()
|
|
17
17
|
with (
|
|
18
18
|
OpenAI(api_key=tokens.openai_api_key.get_secret_value(), http_client=DefaultHttpxClient(http2=True)) as openai,
|
|
19
19
|
TumblrClient(tokens=tokens) as tumblr,
|
|
@@ -59,7 +59,7 @@ class ExamplesWriter(FlowClass):
|
|
|
59
59
|
def get_filtered_posts(self) -> Generator[Post]:
|
|
60
60
|
posts = list(self.get_valid_posts())
|
|
61
61
|
|
|
62
|
-
if Confirm.ask("Remove posts flagged by the OpenAI moderation? This can sometimes resolve errors with fine-tuning validation, but is slow.", default=False):
|
|
62
|
+
if Confirm.ask("[gray62]Remove posts flagged by the OpenAI moderation? This can sometimes resolve errors with fine-tuning validation, but is slow.", default=False):
|
|
63
63
|
removed = 0
|
|
64
64
|
chunk_size = self.get_moderation_chunk_limit()
|
|
65
65
|
with PreviewLive() as live:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from collections.abc import Generator
|
|
2
|
-
from typing import Annotated, Any, ClassVar, Literal, override
|
|
2
|
+
from typing import Annotated, Any, ClassVar, Literal, Self, override
|
|
3
3
|
|
|
4
4
|
import rich
|
|
5
5
|
from keyring import get_password, set_password
|
|
@@ -10,6 +10,14 @@ from requests_oauthlib import OAuth1Session
|
|
|
10
10
|
from rich.panel import Panel
|
|
11
11
|
from rich.prompt import Confirm, Prompt
|
|
12
12
|
|
|
13
|
+
type SerializableSecretStr = Annotated[
|
|
14
|
+
SecretStr,
|
|
15
|
+
PlainSerializer(
|
|
16
|
+
SecretStr.get_secret_value,
|
|
17
|
+
when_used="json-unless-none",
|
|
18
|
+
),
|
|
19
|
+
]
|
|
20
|
+
|
|
13
21
|
|
|
14
22
|
class FullyValidatedModel(BaseModel):
|
|
15
23
|
model_config = ConfigDict(
|
|
@@ -22,13 +30,17 @@ class FullyValidatedModel(BaseModel):
|
|
|
22
30
|
|
|
23
31
|
|
|
24
32
|
class Tokens(FullyValidatedModel):
|
|
33
|
+
class Tumblr(FullyValidatedModel):
|
|
34
|
+
client_key: SerializableSecretStr = SecretStr("")
|
|
35
|
+
client_secret: SerializableSecretStr = SecretStr("")
|
|
36
|
+
resource_owner_key: SerializableSecretStr = SecretStr("")
|
|
37
|
+
resource_owner_secret: SerializableSecretStr = SecretStr("")
|
|
38
|
+
|
|
25
39
|
service_name: ClassVar = "tumblrbot"
|
|
40
|
+
username: ClassVar = "tokens"
|
|
26
41
|
|
|
27
|
-
openai_api_key:
|
|
28
|
-
|
|
29
|
-
tumblr_client_secret: SecretStr = SecretStr("")
|
|
30
|
-
tumblr_resource_owner_key: SecretStr = SecretStr("")
|
|
31
|
-
tumblr_resource_owner_secret: SecretStr = SecretStr("")
|
|
42
|
+
openai_api_key: SerializableSecretStr = SecretStr("")
|
|
43
|
+
tumblr: Tumblr = Tumblr()
|
|
32
44
|
|
|
33
45
|
@staticmethod
|
|
34
46
|
def online_token_prompt(url: str, *tokens: str) -> Generator[SecretStr]:
|
|
@@ -42,46 +54,44 @@ class Tokens(FullyValidatedModel):
|
|
|
42
54
|
|
|
43
55
|
rich.print()
|
|
44
56
|
|
|
57
|
+
@classmethod
|
|
58
|
+
def read_from_keyring(cls) -> Self:
|
|
59
|
+
if json_data := get_password(cls.service_name, cls.username):
|
|
60
|
+
return cls.model_validate_json(json_data)
|
|
61
|
+
return cls()
|
|
62
|
+
|
|
45
63
|
@override
|
|
46
64
|
def model_post_init(self, context: object) -> None:
|
|
47
65
|
super().model_post_init(context)
|
|
48
66
|
|
|
49
|
-
for name, _ in self:
|
|
50
|
-
if value := get_password(self.service_name, name):
|
|
51
|
-
setattr(self, name, value)
|
|
52
|
-
|
|
53
67
|
if not self.openai_api_key.get_secret_value() or Confirm.ask("Reset OpenAI API key?", default=False):
|
|
54
68
|
(self.openai_api_key,) = self.online_token_prompt("https://platform.openai.com/api-keys", "API key")
|
|
55
69
|
|
|
56
|
-
if not all(self.
|
|
57
|
-
self.
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
70
|
+
if not all(self.tumblr.model_dump(mode="json").values()) or Confirm.ask("Reset Tumblr API tokens?", default=False):
|
|
71
|
+
self.tumblr.client_key, self.tumblr.client_secret = self.online_token_prompt("https://tumblr.com/oauth/apps", "consumer key", "consumer secret")
|
|
72
|
+
|
|
73
|
+
with OAuth1Session(
|
|
74
|
+
self.tumblr.client_key.get_secret_value(),
|
|
75
|
+
self.tumblr.client_secret.get_secret_value(),
|
|
76
|
+
) as oauth_session:
|
|
77
|
+
fetch_response = oauth_session.fetch_request_token("http://tumblr.com/oauth/request_token")
|
|
78
|
+
full_authorize_url = oauth_session.authorization_url("http://tumblr.com/oauth/authorize")
|
|
79
|
+
(redirect_response,) = self.online_token_prompt(full_authorize_url, "full redirect URL")
|
|
80
|
+
oauth_response = oauth_session.parse_authorization_response(redirect_response.get_secret_value())
|
|
81
|
+
|
|
82
|
+
with OAuth1Session(
|
|
83
|
+
self.tumblr.client_key.get_secret_value(),
|
|
84
|
+
self.tumblr.client_secret.get_secret_value(),
|
|
66
85
|
fetch_response["oauth_token"],
|
|
67
86
|
fetch_response["oauth_token_secret"],
|
|
68
87
|
verifier=oauth_response["oauth_verifier"],
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
self.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
set_password(self.service_name, name, value.get_secret_value())
|
|
77
|
-
|
|
78
|
-
def get_tumblr_tokens(self) -> tuple[str, str, str, str]:
|
|
79
|
-
return (
|
|
80
|
-
self.tumblr_client_key.get_secret_value(),
|
|
81
|
-
self.tumblr_client_secret.get_secret_value(),
|
|
82
|
-
self.tumblr_resource_owner_key.get_secret_value(),
|
|
83
|
-
self.tumblr_resource_owner_secret.get_secret_value(),
|
|
84
|
-
)
|
|
88
|
+
) as oauth_session:
|
|
89
|
+
oauth_tokens = oauth_session.fetch_access_token("http://tumblr.com/oauth/access_token")
|
|
90
|
+
|
|
91
|
+
self.tumblr.resource_owner_key = oauth_tokens["oauth_token"]
|
|
92
|
+
self.tumblr.resource_owner_secret = oauth_tokens["oauth_token_secret"]
|
|
93
|
+
|
|
94
|
+
set_password(self.service_name, self.username, self.model_dump_json())
|
|
85
95
|
|
|
86
96
|
|
|
87
97
|
class Post(FullyValidatedModel):
|
|
@@ -16,7 +16,7 @@ class TumblrClient(Session, CacheMixin): # pyright: ignore[reportIncompatibleMe
|
|
|
16
16
|
super().__init__(happy_eyeballs=True)
|
|
17
17
|
CacheMixin.__init__(self, use_cache_dir=True)
|
|
18
18
|
|
|
19
|
-
self.auth = OAuth1(
|
|
19
|
+
self.auth = OAuth1(**self.tokens.tumblr.model_dump(mode="json"))
|
|
20
20
|
self.hooks["response"].append(self.response_hook)
|
|
21
21
|
|
|
22
22
|
def __enter__(self) -> Self:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|