3
3
import os
4
4
from datetime import datetime
5
5
from urllib .parse import urljoin
6
+ import json
6
7
7
8
import requests
8
9
@@ -24,6 +25,7 @@ def __init__(
24
25
self ,
25
26
email = None ,
26
27
password = None ,
28
+ cookies_path = None ,
27
29
base_url = None ,
28
30
publication_url = None ,
29
31
debug = False ,
@@ -37,6 +39,9 @@ def __init__(
37
39
Args:
38
40
email:
39
41
password:
42
+ cookies_path
43
+ To re-use your session without logging in each time, you can save your cookies to a json file and then load them in the next session.
44
+ Make sure to re-save your cookies, as they do update over time.
40
45
base_url:
41
46
The base URL to use to contact the Substack API.
42
47
Defaults to https://substack.com/api/v1.
@@ -49,30 +54,39 @@ def __init__(
49
54
50
55
self ._session = requests .Session ()
51
56
52
- if email is not None and password is not None :
57
+ # Load cookies from file if provided
58
+ # Helps with Captcha errors by reusing cookies from "local" auth, then switching to running code in the cloud
59
+ if cookies_path is not None :
60
+ with open (cookies_path , "r" ) as f :
61
+ cookies = json .load (f )
62
+ self ._session .cookies .update (cookies )
63
+
64
+ elif email is not None and password is not None :
53
65
self .login (email , password )
66
+ else :
67
+ raise ValueError ("Must provide email and password or cookies_path to authenticate." )
68
+
69
+ # if the user provided a publication url, then use that
70
+ if publication_url :
71
+ import re
72
+
73
+ # Regular expression to extract subdomain name
74
+ match = re .search (r"https://(.*).substack.com" , publication_url .lower ())
75
+ subdomain = match .group (1 ) if match else None
76
+
77
+ user_publications = self .get_user_publications ()
78
+ # search through publications to find the publication with the matching subdomain
79
+ for publication in user_publications :
80
+ if publication ['subdomain' ] == subdomain :
81
+ # set the current publication to the users publication
82
+ user_publication = publication
83
+ break
84
+ else :
85
+ # get the users primary publication
86
+ user_publication = self .get_user_primary_publication ()
54
87
55
- # if the user provided a publication url, then use that
56
- if publication_url :
57
- import re
58
-
59
- # Regular expression to extract subdomain name
60
- match = re .search (r"https://(.*).substack.com" , publication_url .lower ())
61
- subdomain = match .group (1 ) if match else None
62
-
63
- user_publications = self .get_user_publications ()
64
- # search through publications to find the publication with the matching subdomain
65
- for publication in user_publications :
66
- if publication ['subdomain' ] == subdomain :
67
- # set the current publication to the users publication
68
- user_publication = publication
69
- break
70
- else :
71
- # get the users primary publication
72
- user_publication = self .get_user_primary_publication ()
73
-
74
- # set the current publication to the users primary publication
75
- self .change_publication (user_publication )
88
+ # set the current publication to the users primary publication
89
+ self .change_publication (user_publication )
76
90
77
91
def login (self , email , password ) -> dict :
78
92
"""
@@ -114,6 +128,16 @@ def change_publication(self, publication):
114
128
# sign-in to the publication
115
129
self .signin_for_pub (publication )
116
130
131
+ def export_cookies (self , path : str = "cookies.json" ):
132
+ """
133
+ Export cookies to a json file.
134
+ Args:
135
+ path: path to the json file
136
+ """
137
+ cookies = self ._session .cookies .get_dict ()
138
+ with open (path , "w" ) as f :
139
+ json .dump (cookies , f )
140
+
117
141
@staticmethod
118
142
def _handle_response (response : requests .Response ):
119
143
"""
0 commit comments