ZMediumToMarkdown 2.6.3 → 2.6.6

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4ac9397e4e66a9b14d08c1d9a6d77b61141549d3e7d0b94f4852386898737247
4
- data.tar.gz: bcc9ac34cd734923b0cb57032755bada22bbd3e640e77e0f5b6ca0872afe7279
3
+ metadata.gz: 205308df634eb7992b87b01f7e4c8ae26d3af59d23e5136229e553f935d7798d
4
+ data.tar.gz: cc4e10e1b7751e1d0e71183a76b52a9873c1b60c35e6eb6068df38fbd7546e68
5
5
  SHA512:
6
- metadata.gz: 85a94b063636c2f811704aa2f09328a584b72db9b6f251b7b3b3d67962a92861f9f3feac86026b1e33a10231ac598a76913bb8b8f0bde28d20623d7f752e6b9e
7
- data.tar.gz: eeefcac037b99ba98ccb337bcb5b89fcdb3711ba732e4321c444c47fefa765fb682a2b0e30b8e990d2b738be0c1ccf2bacde2d822c95fde48dbd814c4d8891fe
6
+ metadata.gz: c684e445ff6baa09ad61b943880a516c224d56e73b18cbf1df9ff971d84134ab056af4f353ec269f1715e9250b0d09f3c07d45a7c8c48d86822c4213f3244d5e
7
+ data.tar.gz: 602bd8b81e327ade28c1a2b1197b18f77161ec3d5aff5f45cda0d5e83d812975d5bd2cd2272fe02a3342892b38e2c4028ea61fe4f2cb486b969e1558c8d14551
@@ -18,7 +18,8 @@ class IMGParser < Parser
18
18
 
19
19
  fileName = paragraph.metadata.id #d*fsafwfe.jpg
20
20
 
21
- imageURL = "https://miro.medium.com/max/1400/#{fileName}"
21
+ miro_host = ENV.fetch('MIRO_MEDIUM_HOST', 'https://miro.medium.com')
22
+ imageURL = "#{miro_host}/#{fileName}"
22
23
 
23
24
  imagePathPolicy = PathPolicy.new(pathPolicy.getAbsolutePath(paragraph.postID), pathPolicy.getRelativePath(paragraph.postID))
24
25
  absolutePath = imagePathPolicy.getAbsolutePath(fileName)
data/lib/Post.rb CHANGED
@@ -51,7 +51,8 @@ class Post
51
51
  }
52
52
  ]
53
53
 
54
- body = Request.body(Request.URL("https://medium.com/_/graphql", method = 'POST', data = query));
54
+ host = ENV.fetch('MEDIUM_HOST', 'https://medium.com/_/graphql')
55
+ body = Request.body(Request.URL(host, method = 'POST', data = query));
55
56
  if !body.nil?
56
57
  json = JSON.parse(body)
57
58
  json&.dig(0, "data", "post", "viewerEdge", "fullContent")
@@ -74,7 +75,8 @@ class Post
74
75
 
75
76
  absolutePath = imagePathPolicy.getAbsolutePath(previewImageFIleName)
76
77
 
77
- imageURL = "https://miro.medium.com/max/1400/#{previewImageFIleName}"
78
+ miro_host = ENV.fetch('MIRO_MEDIUM_HOST', 'https://miro.medium.com')
79
+ imageURL = "#{miro_host}/#{previewImageFIleName}"
78
80
 
79
81
  if ImageDownloader.download(absolutePath, imageURL)
80
82
  relativePath = imagePathPolicy.getRelativePath(previewImageFIleName)
data/lib/Request.rb CHANGED
@@ -11,9 +11,35 @@ class Request
11
11
  https = Net::HTTP.new(uri.host, uri.port)
12
12
  https.use_ssl = true
13
13
 
14
+ # --- TLS / Certificate verification setup ---
15
+ # Some OpenSSL builds/configs enable CRL checking, which can fail with:
16
+ # "certificate verify failed (unable to get certificate CRL)".
17
+ # Net::HTTP/OpenSSL does not automatically fetch CRLs, so we use a default
18
+ # cert store and clear CRL-related flags to avoid hard failures while still
19
+ # verifying the peer certificate.
20
+ https.verify_mode = OpenSSL::SSL::VERIFY_PEER
21
+
22
+ store = OpenSSL::X509::Store.new
23
+ store.set_default_paths
24
+ # Ensure no CRL-check flags are enabled by default
25
+ store.flags = 0
26
+ https.cert_store = store
27
+
28
+ # Allow overriding CA bundle paths via environment variables if needed.
29
+ if ENV['SSL_CERT_FILE'] && !ENV['SSL_CERT_FILE'].empty?
30
+ https.ca_file = ENV['SSL_CERT_FILE']
31
+ end
32
+ if ENV['SSL_CERT_DIR'] && !ENV['SSL_CERT_DIR'].empty?
33
+ https.ca_path = ENV['SSL_CERT_DIR']
34
+ end
35
+
36
+ # (Optional) timeouts to avoid hanging on network issues
37
+ https.open_timeout = 10
38
+ https.read_timeout = 30
39
+ # --- end TLS setup ---
40
+
14
41
  if method.upcase == "GET"
15
42
  request = Net::HTTP::Get.new(uri)
16
- request['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0';
17
43
  else
18
44
  request = Net::HTTP::Post.new(uri)
19
45
  request['Content-Type'] = 'application/json'
@@ -22,6 +48,8 @@ class Request
22
48
  end
23
49
  end
24
50
 
51
+ request['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0';
52
+
25
53
  cookiesString = $cookies.reject { |_, value| value.nil? }
26
54
  .map { |key, value| "#{key}=#{value}" }
27
55
  .join("; ");
@@ -63,7 +91,7 @@ class Request
63
91
  response = self.URL(location, method, data, retryCount)
64
92
  end
65
93
  end
66
-
94
+
67
95
  response
68
96
  end
69
97
 
data/lib/User.rb CHANGED
@@ -10,16 +10,23 @@ class User
10
10
  username = username[1...]
11
11
  end
12
12
 
13
- html = Request.html(Request.URL("https://medium.com/@#{username}"))
14
- userId = nil
15
- html.search('script').each do |script|
16
- match = script.to_s[/(userId\:){1}(([0-9|a-z|A-Z])+)/,2]
17
- if !match.nil? && match != ""
18
- userId = match
19
- end
20
- end
13
+ query = [
14
+ {
15
+ "operationName": "UserFollowers",
16
+ "variables": {
17
+ "id": nil,
18
+ "username": username,
19
+ "paging": nil
20
+ },
21
+ "query": "query UserFollowers($username: ID, $id: ID, $paging: PagingOptions) {\n userResult(username: $username, id: $id) {\n __typename\n ... on User {\n id\n followersUserConnection(paging: $paging) {\n pagingInfo {\n next {\n from\n limit\n __typename\n }\n __typename\n }\n users {\n ...FollowList_publisher\n __typename\n }\n __typename\n }\n ...UserCanonicalizer_user\n ...FollowersHeader_publisher\n ...NoFollows_publisher\n __typename\n }\n }\n}\n\nfragment collectionUrl_collection on Collection {\n id\n domain\n slug\n __typename\n}\n\nfragment CollectionAvatar_collection on Collection {\n name\n avatar {\n id\n __typename\n }\n ...collectionUrl_collection\n __typename\n id\n}\n\nfragment SignInOptions_collection on Collection {\n id\n name\n __typename\n}\n\nfragment SignUpOptions_collection on Collection {\n id\n name\n __typename\n}\n\nfragment SusiModal_collection on Collection {\n name\n ...SignInOptions_collection\n ...SignUpOptions_collection\n __typename\n id\n}\n\nfragment PublicationFollowButton_collection on Collection {\n id\n slug\n name\n ...SusiModal_collection\n __typename\n}\n\nfragment PublicationFollowRow_collection on Collection {\n __typename\n id\n name\n description\n ...CollectionAvatar_collection\n ...PublicationFollowButton_collection\n}\n\nfragment userUrl_user on User {\n __typename\n id\n customDomainState {\n live {\n domain\n __typename\n }\n __typename\n }\n hasSubdomain\n username\n}\n\nfragment UserAvatar_user on User {\n __typename\n id\n imageId\n membership {\n tier\n __typename\n id\n }\n name\n username\n ...userUrl_user\n}\n\nfragment isUserVerifiedBookAuthor_user on User {\n verifications {\n isBookAuthor\n __typename\n }\n __typename\n id\n}\n\nfragment SignInOptions_user on User {\n id\n name\n imageId\n __typename\n}\n\nfragment SignUpOptions_user on User {\n id\n name\n imageId\n __typename\n}\n\nfragment SusiModal_user on User {\n ...SignInOptions_user\n ...SignUpOptions_user\n __typename\n id\n}\n\nfragment useNewsletterV3Subscription_newsletterV3 on NewsletterV3 {\n id\n type\n slug\n name\n collection {\n slug\n __typename\n id\n }\n user {\n id\n name\n username\n newsletterV3 {\n id\n __typename\n }\n __typename\n }\n __typename\n}\n\nfragment useNewsletterV3Subscription_user on User {\n id\n username\n newsletterV3 {\n ...useNewsletterV3Subscription_newsletterV3\n __typename\n id\n }\n __typename\n}\n\nfragment useAuthorFollowSubscribeButton_user on User {\n id\n name\n ...useNewsletterV3Subscription_user\n __typename\n}\n\nfragment useAuthorFollowSubscribeButton_newsletterV3 on NewsletterV3 {\n id\n name\n ...useNewsletterV3Subscription_newsletterV3\n __typename\n}\n\nfragment AuthorFollowSubscribeButton_user on User {\n id\n name\n imageId\n ...SusiModal_user\n ...useAuthorFollowSubscribeButton_user\n newsletterV3 {\n id\n ...useAuthorFollowSubscribeButton_newsletterV3\n __typename\n }\n __typename\n}\n\nfragment UserFollowRow_user on User {\n __typename\n id\n name\n bio\n ...UserAvatar_user\n ...isUserVerifiedBookAuthor_user\n ...AuthorFollowSubscribeButton_user\n}\n\nfragment FollowsHeader_publisher on Publisher {\n __typename\n id\n name\n ... on Collection {\n ...collectionUrl_collection\n __typename\n id\n }\n ... on User {\n ...userUrl_user\n __typename\n id\n }\n}\n\nfragment FollowList_publisher on Publisher {\n id\n ... on Collection {\n ...PublicationFollowRow_collection\n __typename\n id\n }\n ... on User {\n ...UserFollowRow_user\n __typename\n id\n }\n __typename\n}\n\nfragment UserCanonicalizer_user on User {\n id\n username\n hasSubdomain\n customDomainState {\n live {\n domain\n __typename\n }\n __typename\n }\n __typename\n}\n\nfragment FollowersHeader_publisher on Publisher {\n ...FollowsHeader_publisher\n ... on Collection {\n subscriberCount\n __typename\n id\n }\n ... on User {\n socialStats {\n followerCount\n __typename\n }\n __typename\n id\n }\n __typename\n}\n\nfragment NoFollows_publisher on Publisher {\n id\n name\n __typename\n}\n"
22
+ }
23
+ ]
24
+
25
+ host = ENV.fetch('MEDIUM_HOST', 'https://medium.com/_/graphql')
26
+ body = Request.body(Request.URL(host, "POST", query))
27
+ json = JSON.parse(body)
21
28
 
22
- userId
29
+ json&.dig(0, "data", "userResult", "id")
23
30
  end
24
31
 
25
32
  def self.fetchUserPosts(userID, from)
@@ -36,7 +43,8 @@ class User
36
43
  }
37
44
  ]
38
45
 
39
- body = Request.body(Request.URL("https://medium.com/_/graphql", "POST", query))
46
+ host = ENV.fetch('MEDIUM_HOST', 'https://medium.com/_/graphql')
47
+ body = Request.body(Request.URL(host, "POST", query))
40
48
  json = JSON.parse(body)
41
49
 
42
50
  nextInfo = json&.dig(0, "data", "userResult", "homepagePostsConnection", "pagingInfo", "next")
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ZMediumToMarkdown
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.6.3
4
+ version: 2.6.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - ZhgChgLi
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-12-14 00:00:00.000000000 Z
10
+ date: 2025-12-15 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: nokogiri