ZMediumToMarkdown 2.6.5 → 2.6.7
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 +4 -4
- data/lib/Parsers/IMGParser.rb +2 -1
- data/lib/Post.rb +58 -33
- data/lib/Request.rb +2 -3
- data/lib/User.rb +18 -10
- data/lib/ZMediumFetcher.rb +1 -8
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fec9548cdcae9471f64f93f498f2ca1e13bdbe743455efb3b4df57f4802e0fa9
|
|
4
|
+
data.tar.gz: 99fbfcb556b08d91e38b46311ef76e2240a510ba4536c08a69fdf747caacd477
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c898f126a0d27117564b989ec95153a5f4ea835d5f58060cddf4a1d9b57e4fa677e04f264cbec60853cacd1666a26a63f96d899d93b1008f56cca712ca52e656
|
|
7
|
+
data.tar.gz: b6a228d0817cff2263a98fb4bd9d6041f553c927c5f779c512feb647c1825dc4dc0d9f4f939b3877f19d237d4bd48c3005c8ea4c553df8130eb5a865184884d0
|
data/lib/Parsers/IMGParser.rb
CHANGED
|
@@ -18,7 +18,8 @@ class IMGParser < Parser
|
|
|
18
18
|
|
|
19
19
|
fileName = paragraph.metadata.id #d*fsafwfe.jpg
|
|
20
20
|
|
|
21
|
-
|
|
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
|
-
|
|
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")
|
|
@@ -60,50 +61,74 @@ class Post
|
|
|
60
61
|
end
|
|
61
62
|
end
|
|
62
63
|
|
|
63
|
-
def self.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
def self.parsePostInfo(postID, pathPolicy)
|
|
65
|
+
query = [
|
|
66
|
+
{
|
|
67
|
+
"operationName": "PostPageQuery",
|
|
68
|
+
"variables": {
|
|
69
|
+
"postId": postID,
|
|
70
|
+
"postMeteringOptions": {
|
|
71
|
+
"referrer": "https://medium.com/me/stories"
|
|
72
|
+
},
|
|
73
|
+
"includeShouldFollowPost": false
|
|
74
|
+
},
|
|
75
|
+
"query": "query PostPageQuery($postId: ID!, $postMeteringOptions: PostMeteringOptions, $includeShouldFollowPost: Boolean!) {\n postResult(id: $postId) {\n __typename\n ...PostResultError_postResult\n ... on Post {\n id\n collection {\n id\n googleAnalyticsId\n ...FloatingPublicationBio_collection\n ...MoreFromAuthorAndMaybePub_collection\n ...PostPublishersInfoSection_collection\n ...PublicationNav_collection\n __typename\n }\n content(postMeteringOptions: $postMeteringOptions) {\n isLockedPreviewOnly\n __typename\n }\n creator {\n id\n ...MastodonVerificationLink_user\n ...SuspendedBannerLoader_user\n ...MoreFromAuthorAndMaybePub_user\n ...PostPublishersInfoSection_user\n __typename\n }\n inResponseToEntityType\n isLocked\n ...Wall_post\n ...InteractivePostBody_post\n ...WithResponsesSidebar_post\n ...PostCanonicalizer_post\n ...PostFooterActionsBar_post\n ...PostReadTracker_post\n ...PostMetadata_post\n ...SuspendedBannerLoader_post\n ...PostFooterInfo_post\n ...PostBodyInserts_post\n ...PostNoteMissingToast_post\n ...usePostTracking_post\n ...InResponseToEntityPreview_post\n ...PostPublishedDialog_prerequisite_post\n ...PostResponses_post\n ...PostPublishersInfoSection_post\n ...UseSubscribeToAuthorOnScroll_post\n __typename\n }\n }\n}\n\nfragment UnavailableForLegalReasonsScreen_unavailableForLegalReasons on UnavailableForLegalReasons {\n lumenId\n __typename\n}\n\nfragment WithheldInCountryScreen_withheldInCountry on WithheldInCountry {\n lumenId\n __typename\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 PublisherDescription_publisher on Publisher {\n __typename\n id\n ... on Collection {\n description\n __typename\n id\n }\n ... on User {\n bio\n __typename\n id\n }\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 isUserVerifiedBookAuthor_user on User {\n verifications {\n isBookAuthor\n __typename\n }\n __typename\n id\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 PublisherLink_user on User {\n ...userUrl_user\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 PublisherLink_collection on Collection {\n ...collectionUrl_collection\n __typename\n id\n}\n\nfragment PublisherName_publisher on Publisher {\n id\n name\n __typename\n}\n\nfragment PublisherFollowersCount_publisher on Publisher {\n id\n __typename\n id\n ... on Collection {\n slug\n subscriberCount\n ...collectionUrl_collection\n __typename\n id\n }\n ... on User {\n socialStats {\n followerCount\n __typename\n }\n username\n ...userUrl_user\n __typename\n id\n }\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 PublisherAvatar_publisher on Publisher {\n __typename\n ... on Collection {\n id\n ...CollectionAvatar_collection\n __typename\n }\n ... on User {\n id\n ...UserAvatar_user\n __typename\n }\n}\n\nfragment usePostUrl_post on Post {\n id\n creator {\n ...userUrl_user\n __typename\n id\n }\n collection {\n id\n domain\n slug\n __typename\n }\n isSeries\n mediumUrl\n sequence {\n slug\n __typename\n }\n uniqueSlug\n __typename\n}\n\nfragment CollectionLastPostDate_collection on Collection {\n __typename\n ... on Collection {\n latestPostsConnection(paging: {limit: 1}) {\n posts {\n id\n firstPublishedAt\n ...usePostUrl_post\n __typename\n }\n __typename\n }\n __typename\n id\n }\n id\n}\n\nfragment PublisherFollowingCount_publisher on Publisher {\n __typename\n id\n ... on User {\n socialStats {\n followingCount\n collectionFollowingCount\n __typename\n }\n username\n __typename\n id\n }\n}\n\nfragment PublisherFollowingCountOrLastPostDate_publisher on Publisher {\n __typename\n ... on Collection {\n ...CollectionLastPostDate_collection\n __typename\n id\n }\n ...PublisherFollowingCount_publisher\n}\n\nfragment PostPublisherInfo_publisher on Publisher {\n __typename\n id\n name\n ... on User {\n ...isUserVerifiedBookAuthor_user\n ...PublisherLink_user\n ...AuthorFollowSubscribeButton_user\n __typename\n id\n }\n ... on Collection {\n ...PublisherLink_collection\n ...PublicationFollowButton_collection\n __typename\n id\n }\n ...PublisherName_publisher\n ...PublisherFollowersCount_publisher\n ...PublisherDescription_publisher\n ...PublisherAvatar_publisher\n ...PublisherFollowingCountOrLastPostDate_publisher\n}\n\nfragment PublicationNavMobileItems_collection on Collection {\n id\n ...PublicationFollowButton_collection\n __typename\n}\n\nfragment SusiModal_post on Post {\n id\n creator {\n id\n __typename\n }\n __typename\n}\n\nfragment SusiClickable_post on Post {\n id\n mediumUrl\n ...SusiModal_post\n __typename\n}\n\nfragment RegWall_post on Post {\n id\n lockedSource\n ...SusiClickable_post\n __typename\n}\n\nfragment EntityPaywall_post on Post {\n id\n creator {\n name\n __typename\n id\n }\n __typename\n}\n\nfragment AspirationalPaywall_post on Post {\n ...EntityPaywall_post\n __typename\n id\n}\n\nfragment ProgrammingPaywall_post on Post {\n ...EntityPaywall_post\n __typename\n id\n}\n\nfragment Paywall_post on Post {\n id\n creator {\n id\n name\n imageId\n __typename\n }\n primaryTopic {\n slug\n __typename\n id\n }\n topics {\n slug\n __typename\n }\n ...AspirationalPaywall_post\n ...ProgrammingPaywall_post\n __typename\n}\n\nfragment DropCap_image on ImageMetadata {\n id\n originalHeight\n originalWidth\n __typename\n}\n\nfragment MarkupNode_data_dropCapImage on ImageMetadata {\n ...DropCap_image\n __typename\n id\n}\n\nfragment Markups_markup on Markup {\n type\n start\n end\n href\n anchorType\n userId\n linkMetadata {\n httpStatus\n __typename\n }\n __typename\n}\n\nfragment Markups_paragraph on Paragraph {\n name\n text\n hasDropCap\n dropCapImage {\n ...MarkupNode_data_dropCapImage\n __typename\n id\n }\n markups {\n ...Markups_markup\n __typename\n }\n __typename\n id\n}\n\nfragment ParagraphRefsMapContext_paragraph on Paragraph {\n id\n name\n text\n __typename\n}\n\nfragment PostViewNoteCard_paragraph on Paragraph {\n name\n __typename\n id\n}\n\nfragment PostAnnotationsMarker_paragraph on Paragraph {\n ...PostViewNoteCard_paragraph\n __typename\n id\n}\n\nfragment ImageParagraph_paragraph on Paragraph {\n href\n layout\n metadata {\n id\n originalHeight\n originalWidth\n focusPercentX\n focusPercentY\n alt\n __typename\n }\n ...Markups_paragraph\n ...ParagraphRefsMapContext_paragraph\n ...PostAnnotationsMarker_paragraph\n __typename\n id\n}\n\nfragment TextParagraph_paragraph on Paragraph {\n type\n hasDropCap\n codeBlockMetadata {\n mode\n lang\n __typename\n }\n ...Markups_paragraph\n ...ParagraphRefsMapContext_paragraph\n __typename\n id\n}\n\nfragment IframeParagraph_paragraph on Paragraph {\n type\n iframe {\n mediaResource {\n id\n iframeSrc\n iframeHeight\n iframeWidth\n title\n __typename\n }\n __typename\n }\n layout\n ...Markups_paragraph\n __typename\n id\n}\n\nfragment GenericMixtapeParagraph_paragraph on Paragraph {\n text\n mixtapeMetadata {\n href\n thumbnailImageId\n __typename\n }\n markups {\n start\n end\n type\n href\n __typename\n }\n __typename\n id\n}\n\nfragment MixtapeParagraph_paragraph on Paragraph {\n type\n mixtapeMetadata {\n href\n mediaResource {\n mediumCatalog {\n id\n __typename\n }\n __typename\n }\n __typename\n }\n ...GenericMixtapeParagraph_paragraph\n __typename\n id\n}\n\nfragment CodeBlockParagraph_paragraph on Paragraph {\n codeBlockMetadata {\n lang\n mode\n __typename\n }\n __typename\n id\n}\n\nfragment PostBodyParagraph_paragraph on Paragraph {\n name\n type\n ...ImageParagraph_paragraph\n ...TextParagraph_paragraph\n ...IframeParagraph_paragraph\n ...MixtapeParagraph_paragraph\n ...CodeBlockParagraph_paragraph\n __typename\n id\n}\n\nfragment PostBodySection_paragraph on Paragraph {\n name\n ...PostBodyParagraph_paragraph\n __typename\n id\n}\n\nfragment normalizedBodyModel_richText_paragraphs_markups on Markup {\n type\n __typename\n}\n\nfragment getParagraphHighlights_paragraph on Paragraph {\n name\n __typename\n id\n}\n\nfragment getParagraphPrivateNotes_paragraph on Paragraph {\n name\n __typename\n id\n}\n\nfragment normalizedBodyModel_richText_paragraphs on Paragraph {\n markups {\n ...normalizedBodyModel_richText_paragraphs_markups\n __typename\n }\n codeBlockMetadata {\n lang\n mode\n __typename\n }\n ...getParagraphHighlights_paragraph\n ...getParagraphPrivateNotes_paragraph\n __typename\n id\n}\n\nfragment getSectionEndIndex_section on Section {\n startIndex\n __typename\n}\n\nfragment getParagraphStyles_richText on RichText {\n paragraphs {\n text\n type\n __typename\n }\n sections {\n ...getSectionEndIndex_section\n __typename\n }\n __typename\n}\n\nfragment paragraphExtendsImageGrid_paragraph on Paragraph {\n layout\n type\n __typename\n id\n}\n\nfragment getSeriesParagraphTopSpacings_richText on RichText {\n paragraphs {\n id\n __typename\n }\n sections {\n ...getSectionEndIndex_section\n __typename\n }\n __typename\n}\n\nfragment getPostParagraphTopSpacings_richText on RichText {\n paragraphs {\n type\n layout\n text\n codeBlockMetadata {\n lang\n mode\n __typename\n }\n __typename\n }\n sections {\n ...getSectionEndIndex_section\n __typename\n }\n __typename\n}\n\nfragment getParagraphSpaces_richText on RichText {\n paragraphs {\n layout\n metadata {\n originalHeight\n originalWidth\n id\n __typename\n }\n type\n ...paragraphExtendsImageGrid_paragraph\n __typename\n }\n ...getSeriesParagraphTopSpacings_richText\n ...getPostParagraphTopSpacings_richText\n __typename\n}\n\nfragment normalizedBodyModel_richText on RichText {\n paragraphs {\n ...normalizedBodyModel_richText_paragraphs\n __typename\n }\n sections {\n startIndex\n ...getSectionEndIndex_section\n __typename\n }\n ...getParagraphStyles_richText\n ...getParagraphSpaces_richText\n __typename\n}\n\nfragment PostBody_bodyModel on RichText {\n sections {\n name\n startIndex\n textLayout\n imageLayout\n backgroundImage {\n id\n originalHeight\n originalWidth\n __typename\n }\n videoLayout\n backgroundVideo {\n videoId\n originalHeight\n originalWidth\n previewImageId\n __typename\n }\n __typename\n }\n paragraphs {\n id\n ...PostBodySection_paragraph\n __typename\n }\n ...normalizedBodyModel_richText\n __typename\n}\n\nfragment HighlighSegmentContext_paragraph on Paragraph {\n ...ParagraphRefsMapContext_paragraph\n __typename\n id\n}\n\nfragment NormalizeHighlights_paragraph on Paragraph {\n name\n text\n __typename\n id\n}\n\nfragment HighlightMenuOption_post on Post {\n id\n latestPublishedVersion\n __typename\n}\n\nfragment RespondMenuOption_post on Post {\n id\n latestPublishedVersion\n __typename\n}\n\nfragment ShareMenuOption_post on Post {\n id\n latestPublishedVersion\n creator {\n name\n __typename\n id\n }\n __typename\n}\n\nfragment SelectionMenuPopover_post on Post {\n isPublished\n allowResponses\n isLimitedState\n responsesLocked\n visibility\n isLocked\n creator {\n allowNotes\n __typename\n id\n }\n ...HighlightMenuOption_post\n ...RespondMenuOption_post\n ...ShareMenuOption_post\n __typename\n id\n}\n\nfragment SelectionMenu_post on Post {\n isPublished\n creator {\n allowNotes\n __typename\n id\n }\n ...SelectionMenuPopover_post\n __typename\n id\n}\n\nfragment PostNewNoteCard_post on Post {\n id\n latestPublishedVersion\n __typename\n}\n\nfragment ActiveSelectionContext_post on Post {\n id\n ...SelectionMenu_post\n ...PostNewNoteCard_post\n __typename\n}\n\nfragment PostBodyParagraph_post on Post {\n creator {\n id\n __typename\n }\n __typename\n id\n}\n\nfragment SubscribeToAuthorParagraph_post on Post {\n creator {\n name\n __typename\n id\n }\n mediumUrl\n __typename\n id\n}\n\nfragment UpsellParagraph_post on Post {\n id\n creator {\n id\n __typename\n }\n ...SubscribeToAuthorParagraph_post\n __typename\n}\n\nfragment UseIsElligibleForSubscribeToAuthor_post on Post {\n id\n isLocked\n __typename\n}\n\nfragment useIsEligibleToBecomeMember_post on Post {\n id\n isLocked\n creator {\n id\n membership {\n id\n __typename\n }\n __typename\n }\n __typename\n}\n\nfragment UpsellPostParagraphContext_post on Post {\n ...PostBodyParagraph_post\n ...UpsellParagraph_post\n ...UseIsElligibleForSubscribeToAuthor_post\n ...useIsEligibleToBecomeMember_post\n __typename\n id\n}\n\nfragment ReportUserMenuItem_post on Post {\n __typename\n id\n creator {\n id\n __typename\n }\n ...SusiClickable_post\n}\n\nfragment useHideResponseParent_post on Post {\n __typename\n id\n creator {\n id\n __typename\n }\n collection {\n id\n viewerEdge {\n id\n isEditor\n __typename\n }\n __typename\n }\n}\n\nfragment HideResponseMenuItemParent_post on Post {\n id\n ...useHideResponseParent_post\n __typename\n}\n\nfragment BlockUserMenuItem_post on Post {\n __typename\n id\n creator {\n id\n __typename\n }\n}\n\nfragment UndoClapsMenuItem_post on Post {\n id\n clapCount\n __typename\n}\n\nfragment DeleteResponseMenuItem_post on Post {\n creator {\n id\n __typename\n }\n __typename\n id\n}\n\nfragment useReportStory_post on Post {\n id\n creator {\n id\n __typename\n }\n __typename\n}\n\nfragment ReportResponseDialog_post on Post {\n __typename\n id\n creator {\n id\n __typename\n }\n ...useHideResponseParent_post\n ...useReportStory_post\n}\n\nfragment ResponsePopoverMenu_post on Post {\n id\n responseDistribution\n ...ReportUserMenuItem_post\n ...HideResponseMenuItemParent_post\n ...BlockUserMenuItem_post\n ...UndoClapsMenuItem_post\n ...DeleteResponseMenuItem_post\n ...ReportResponseDialog_post\n __typename\n}\n\nfragment ResponseHeaderParentEntity_post on Post {\n __typename\n creator {\n id\n __typename\n }\n ...ResponsePopoverMenu_post\n id\n}\n\nfragment SimpleResponseParentEntity_post on Post {\n ...ResponseHeaderParentEntity_post\n __typename\n id\n}\n\nfragment ReadOrEditSimpleResponseParentEntity_post on Post {\n __typename\n id\n ...SimpleResponseParentEntity_post\n}\n\nfragment StoryResponseParentEntity_post on Post {\n id\n ...ResponseHeaderParentEntity_post\n __typename\n}\n\nfragment ThreadedReplyParentEntity_post on Post {\n __typename\n id\n ...ReadOrEditSimpleResponseParentEntity_post\n ...StoryResponseParentEntity_post\n}\n\nfragment ThreadedRepliesParentEntity_post on Post {\n __typename\n id\n ...ThreadedReplyParentEntity_post\n}\n\nfragment ThreadedResponsesSidebarContent_post on Post {\n id\n latestPublishedVersion\n postResponses {\n count\n __typename\n }\n collection {\n id\n viewerEdge {\n id\n isEditor\n __typename\n }\n __typename\n }\n creator {\n id\n __typename\n }\n ...ThreadedRepliesParentEntity_post\n __typename\n}\n\nfragment ThreadedResponsesSidebar_post on Post {\n id\n ...ThreadedResponsesSidebarContent_post\n __typename\n}\n\nfragment SusiClickable_user on User {\n ...SusiModal_user\n __typename\n id\n}\n\nfragment MultiVoteCount_post on Post {\n id\n __typename\n}\n\nfragment MultiVote_post on Post {\n id\n creator {\n id\n ...SusiClickable_user\n __typename\n }\n isPublished\n ...SusiClickable_post\n collection {\n id\n slug\n __typename\n }\n isLimitedState\n ...MultiVoteCount_post\n __typename\n}\n\nfragment useCopyFriendLink_post on Post {\n ...usePostUrl_post\n __typename\n id\n}\n\nfragment UpsellClickable_post on Post {\n id\n collection {\n id\n __typename\n }\n sequence {\n sequenceId\n __typename\n }\n creator {\n id\n __typename\n }\n __typename\n}\n\nfragment FriendLink_post on Post {\n id\n ...SusiClickable_post\n ...useCopyFriendLink_post\n ...UpsellClickable_post\n __typename\n}\n\nfragment PostSharePopover_post on Post {\n id\n mediumUrl\n title\n isPublished\n isLocked\n ...usePostUrl_post\n ...FriendLink_post\n __typename\n}\n\nfragment FollowMenuOptions_user on User {\n id\n ...AuthorFollowSubscribeButton_user\n __typename\n}\n\nfragment FollowMenuOptions_collection on Collection {\n id\n ...PublicationFollowButton_collection\n __typename\n}\n\nfragment ClapMutation_post on Post {\n __typename\n id\n clapCount\n ...MultiVoteCount_post\n}\n\nfragment OverflowMenuItemUndoClaps_post on Post {\n id\n clapCount\n ...ClapMutation_post\n __typename\n}\n\nfragment AddToCatalogBase_post on Post {\n id\n isPublished\n ...SusiClickable_post\n __typename\n}\n\nfragment NegativeSignalModal_publisher on Publisher {\n __typename\n id\n name\n}\n\nfragment NegativeSignalModal_post on Post {\n id\n creator {\n ...NegativeSignalModal_publisher\n viewerEdge {\n id\n isMuting\n __typename\n }\n __typename\n id\n }\n collection {\n ...NegativeSignalModal_publisher\n viewerEdge {\n id\n isMuting\n __typename\n }\n __typename\n id\n }\n __typename\n}\n\nfragment ExplicitSignalMenuOptions_post on Post {\n ...NegativeSignalModal_post\n __typename\n id\n}\n\nfragment OverflowMenu_post on Post {\n id\n creator {\n id\n ...FollowMenuOptions_user\n __typename\n }\n collection {\n id\n ...FollowMenuOptions_collection\n __typename\n }\n ...OverflowMenuItemUndoClaps_post\n ...AddToCatalogBase_post\n ...ExplicitSignalMenuOptions_post\n __typename\n}\n\nfragment OverflowMenuButton_post on Post {\n id\n visibility\n ...OverflowMenu_post\n __typename\n}\n\nfragment AddToCatalogBookmarkButton_post on Post {\n ...AddToCatalogBase_post\n __typename\n id\n}\n\nfragment BookmarkButton_post on Post {\n visibility\n ...SusiClickable_post\n ...AddToCatalogBookmarkButton_post\n __typename\n id\n}\n\nfragment getPostContentAsString_post on Post {\n content(postMeteringOptions: $postMeteringOptions) {\n bodyModel {\n paragraphs {\n text\n type\n mixtapeMetadata {\n href\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n id\n}\n\nfragment postMetaDescription_post on Post {\n id\n title\n seoDescription\n metaDescription\n creator {\n id\n name\n __typename\n }\n collection {\n id\n name\n __typename\n }\n previewContent {\n subtitle\n __typename\n }\n ...getPostContentAsString_post\n __typename\n}\n\nfragment shortformPostMetaDescription_post on Post {\n id\n metaDescription\n seoDescription\n shortformType\n title\n ...getPostContentAsString_post\n __typename\n}\n\nfragment shouldIndexPost_post on Post {\n id\n firstPublishedAt\n isShortform\n shortformType\n visibility\n ...getPostContentAsString_post\n viewerEdge {\n shouldIndexPostForExternalSearch\n __typename\n id\n }\n __typename\n}\n\nfragment shouldFollowPost_post on Post {\n viewerEdge {\n id\n shouldFollowPostForExternalSearch\n __typename\n }\n __typename\n id\n}\n\nfragment appendPostContext_post on Post {\n id\n sequence {\n title\n __typename\n }\n collection {\n name\n __typename\n id\n }\n creator {\n name\n __typename\n id\n }\n __typename\n}\n\nfragment maybeAppendProductName_collection on Collection {\n id\n domain\n __typename\n}\n\nfragment shortformPostTitle_post on Post {\n id\n title\n seoTitle\n shortformType\n ...getPostContentAsString_post\n ...appendPostContext_post\n collection {\n ...maybeAppendProductName_collection\n __typename\n id\n }\n __typename\n}\n\nfragment GetTitleIndexMap_bodyModel on RichText {\n paragraphs {\n type\n text\n __typename\n }\n __typename\n}\n\nfragment getTitleDetails_post on Post {\n id\n content(postMeteringOptions: $postMeteringOptions) {\n bodyModel {\n ...GetTitleIndexMap_bodyModel\n __typename\n }\n __typename\n }\n ...getPostContentAsString_post\n __typename\n}\n\nfragment postTitle_post on Post {\n id\n title\n seoTitle\n firstPublishedAt\n ...getPostContentAsString_post\n ...appendPostContext_post\n collection {\n id\n name\n domain\n ...maybeAppendProductName_collection\n __typename\n }\n creator {\n name\n __typename\n id\n }\n previewContent {\n subtitle\n __typename\n }\n __typename\n}\n\nfragment getTitleForPost_post on Post {\n id\n title\n ...postTitle_post\n ...getTitleDetails_post\n __typename\n}\n\nfragment postHasImage_post on Post {\n content(postMeteringOptions: $postMeteringOptions) {\n bodyModel {\n paragraphs {\n type\n __typename\n }\n __typename\n }\n __typename\n }\n __typename\n id\n}\n\nfragment PostFooterTags_post on Post {\n id\n tags {\n __typename\n id\n displayTitle\n normalizedTagSlug\n }\n __typename\n}\n\nfragment OverlappingAvatars_user on User {\n __typename\n id\n imageId\n name\n username\n ...userUrl_user\n}\n\nfragment AuthorByline_user on User {\n __typename\n id\n name\n ...isUserVerifiedBookAuthor_user\n ...userUrl_user\n ...AuthorFollowSubscribeButton_user\n}\n\nfragment PostByline_user on User {\n ...AuthorByline_user\n __typename\n id\n}\n\nfragment PostBodyInserts_paragraph on Paragraph {\n name\n text\n type\n __typename\n id\n}\n\nfragment AuthorFollowSubscribeButton_post on Post {\n id\n ...SusiModal_post\n __typename\n}\n\nfragment AuthorByline_post on Post {\n ...AuthorFollowSubscribeButton_post\n __typename\n id\n}\n\nfragment shouldShowPublishedInStatus_post on Post {\n statusForCollection\n isPublished\n __typename\n id\n}\n\nfragment CollectionByline_post on Post {\n ...shouldShowPublishedInStatus_post\n __typename\n id\n}\n\nfragment BoldCollectionName_collection on Collection {\n id\n name\n __typename\n}\n\nfragment DraftStatus_post on Post {\n id\n pendingCollection {\n id\n creator {\n id\n __typename\n }\n ...BoldCollectionName_collection\n __typename\n }\n statusForCollection\n creator {\n id\n __typename\n }\n isPublished\n __typename\n}\n\nfragment PostBylineDescription_post on Post {\n id\n isNewsletter\n collection {\n slug\n __typename\n id\n }\n ...CollectionByline_post\n ...DraftStatus_post\n __typename\n}\n\nfragment MaybeTextToSpeech_post on Post {\n id\n detectedLanguage\n wordCount\n isPublished\n __typename\n}\n\nfragment PostByline_post on Post {\n id\n postResponses {\n count\n __typename\n }\n allowResponses\n isLimitedState\n isPublished\n ...AuthorByline_post\n ...PostBylineDescription_post\n ...MultiVote_post\n ...BookmarkButton_post\n ...MaybeTextToSpeech_post\n ...PostSharePopover_post\n ...OverflowMenuButton_post\n __typename\n}\n\nfragment useShouldShowPostPageMeter_post on Post {\n id\n creator {\n id\n __typename\n }\n isLocked\n lockedSource\n content(postMeteringOptions: $postMeteringOptions) {\n isLockedPreviewOnly\n validatedShareKey\n __typename\n }\n __typename\n}\n\nfragment FriendLinkSharer_user on User {\n id\n name\n ...userUrl_user\n __typename\n}\n\nfragment FriendLinkMeter_postContent on PostContent {\n validatedShareKey\n shareKeyCreator {\n ...FriendLinkSharer_user\n __typename\n id\n }\n __typename\n}\n\nfragment MeterClickable_post on Post {\n id\n ...UpsellClickable_post\n __typename\n}\n\nfragment FriendLinkMeter_post on Post {\n id\n content(postMeteringOptions: $postMeteringOptions) {\n ...FriendLinkMeter_postContent\n __typename\n }\n creator {\n ...FriendLinkSharer_user\n __typename\n id\n }\n ...MeterClickable_post\n __typename\n}\n\nfragment PostPageMeter_post on Post {\n id\n content(postMeteringOptions: $postMeteringOptions) {\n isLockedPreviewOnly\n __typename\n }\n ...FriendLinkMeter_post\n ...MeterClickable_post\n __typename\n}\n\nfragment PostPageStar_post on Post {\n id\n creator {\n id\n __typename\n }\n isLocked\n __typename\n}\n\nfragment FeaturedStoryPopover_post on Post {\n id\n collection {\n id\n name\n slug\n ...CollectionAvatar_collection\n __typename\n }\n __typename\n}\n\nfragment FeaturedStoryLabel_post on Post {\n isFeaturedInPublishedPublication\n id\n creator {\n id\n __typename\n }\n collection {\n id\n __typename\n }\n ...FeaturedStoryPopover_post\n __typename\n}\n\nfragment StarAndFeaturedInsert_post on Post {\n isLocked\n ...PostPageStar_post\n ...FeaturedStoryLabel_post\n __typename\n id\n}\n\nfragment usePostClientViewedReporter_post on Post {\n id\n isPublished\n isLocked\n collection {\n id\n slug\n __typename\n }\n content(postMeteringOptions: $postMeteringOptions) {\n validatedShareKey\n isLockedPreviewOnly\n __typename\n }\n __typename\n}\n\nfragment PostResponseParentEntity_post on Post {\n ...ReadOrEditSimpleResponseParentEntity_post\n ...StoryResponseParentEntity_post\n __typename\n id\n}\n\nfragment PostResponsesContent_post on Post {\n responsesLocked\n postResponses {\n count\n __typename\n }\n creator {\n id\n __typename\n }\n collection {\n viewerEdge {\n isEditor\n __typename\n id\n }\n __typename\n id\n }\n ...PostResponseParentEntity_post\n __typename\n id\n}\n\nfragment PublicationFollowButton_post on Post {\n id\n ...SusiModal_post\n __typename\n}\n\nfragment PostPublisherInfo_post on Post {\n id\n ...AuthorFollowSubscribeButton_post\n ...PublicationFollowButton_post\n __typename\n}\n\nfragment PostResultError_postResult on PostResult {\n __typename\n ... on Post {\n id\n __typename\n }\n ... on UnavailableForLegalReasons {\n ...UnavailableForLegalReasonsScreen_unavailableForLegalReasons\n __typename\n }\n ... on WithheldInCountry {\n ...WithheldInCountryScreen_withheldInCountry\n __typename\n }\n}\n\nfragment FloatingPublicationBio_collection on Collection {\n id\n ...CollectionAvatar_collection\n ...PublisherDescription_publisher\n ...PublicationFollowButton_collection\n __typename\n}\n\nfragment MoreFromAuthorAndMaybePub_collection on Collection {\n id\n name\n ...collectionUrl_collection\n __typename\n}\n\nfragment PostPublishersInfoSection_collection on Collection {\n ...PostPublisherInfo_publisher\n __typename\n id\n}\n\nfragment PublicationNav_collection on Collection {\n id\n name\n slug\n compatV3 {\n id\n theme {\n accentColor {\n rgb\n __typename\n }\n __typename\n }\n __typename\n }\n ...PublicationNavMobileItems_collection\n __typename\n}\n\nfragment MastodonVerificationLink_user on User {\n id\n linkedAccounts {\n mastodon {\n domain\n username\n __typename\n id\n }\n __typename\n id\n }\n __typename\n}\n\nfragment SuspendedBannerLoader_user on User {\n id\n isSuspended\n __typename\n}\n\nfragment MoreFromAuthorAndMaybePub_user on User {\n __typename\n id\n name\n imageId\n ...userUrl_user\n}\n\nfragment PostPublishersInfoSection_user on User {\n ...PostPublisherInfo_publisher\n __typename\n id\n}\n\nfragment Wall_post on Post {\n content(postMeteringOptions: $postMeteringOptions) {\n isLockedPreviewOnly\n __typename\n }\n isLocked\n isMarkedPaywallOnly\n ...RegWall_post\n ...Paywall_post\n __typename\n id\n}\n\nfragment InteractivePostBody_post on Post {\n id\n isLimitedState\n isPublished\n allowResponses\n content(postMeteringOptions: $postMeteringOptions) {\n isLockedPreviewOnly\n bodyModel {\n ...PostBody_bodyModel\n paragraphs {\n ...HighlighSegmentContext_paragraph\n ...NormalizeHighlights_paragraph\n __typename\n }\n __typename\n }\n __typename\n }\n creator {\n id\n allowNotes\n __typename\n }\n ...ActiveSelectionContext_post\n ...UpsellPostParagraphContext_post\n __typename\n}\n\nfragment WithResponsesSidebar_post on Post {\n id\n ...ThreadedResponsesSidebar_post\n __typename\n}\n\nfragment PostCanonicalizer_post on Post {\n mediumUrl\n __typename\n id\n}\n\nfragment PostFooterActionsBar_post on Post {\n id\n visibility\n allowResponses\n postResponses {\n count\n __typename\n }\n isLimitedState\n creator {\n id\n __typename\n }\n collection {\n id\n __typename\n }\n ...MultiVote_post\n ...PostSharePopover_post\n ...OverflowMenuButton_post\n ...BookmarkButton_post\n __typename\n}\n\nfragment PostReadTracker_post on Post {\n id\n collection {\n slug\n __typename\n id\n }\n sequence {\n sequenceId\n __typename\n }\n content(postMeteringOptions: $postMeteringOptions) {\n isLockedPreviewOnly\n __typename\n }\n __typename\n}\n\nfragment PostMetadata_post on Post {\n id\n socialTitle\n socialDek\n canonicalUrl\n mediumUrl\n metaDescription\n latestPublishedAt\n visibility\n isLimitedState\n readingTime\n creator {\n name\n twitterScreenName\n ...userUrl_user\n __typename\n id\n }\n collection {\n twitterUsername\n facebookPageId\n __typename\n id\n }\n previewContent {\n subtitle\n __typename\n }\n previewImage {\n id\n alt\n focusPercentX\n focusPercentY\n originalHeight\n originalWidth\n __typename\n }\n isShortform\n seoMetaTags {\n jsonLd\n __typename\n }\n ...postMetaDescription_post\n ...shortformPostMetaDescription_post\n ...shouldIndexPost_post\n ...shouldFollowPost_post @include(if: $includeShouldFollowPost)\n ...shortformPostTitle_post\n ...getTitleDetails_post\n ...getTitleForPost_post\n ...postHasImage_post\n __typename\n}\n\nfragment SuspendedBannerLoader_post on Post {\n id\n isSuspended\n __typename\n}\n\nfragment PostFooterInfo_post on Post {\n id\n license\n visibility\n ...PostFooterTags_post\n __typename\n}\n\nfragment PostBodyInserts_post on Post {\n creator {\n ...OverlappingAvatars_user\n ...PostByline_user\n __typename\n id\n }\n firstPublishedAt\n isLocked\n isShortform\n readingTime\n isFeaturedInPublishedPublication\n content(postMeteringOptions: $postMeteringOptions) {\n isLockedPreviewOnly\n bodyModel {\n paragraphs {\n ...PostBodyInserts_paragraph\n __typename\n }\n sections {\n startIndex\n __typename\n }\n __typename\n }\n __typename\n }\n ...PostByline_post\n ...useShouldShowPostPageMeter_post\n ...PostPageMeter_post\n ...StarAndFeaturedInsert_post\n __typename\n id\n}\n\nfragment PostNoteMissingToast_post on Post {\n id\n __typename\n}\n\nfragment usePostTracking_post on Post {\n ...usePostClientViewedReporter_post\n __typename\n id\n}\n\nfragment InResponseToEntityPreview_post on Post {\n id\n inResponseToEntityType\n __typename\n}\n\nfragment PostPublishedDialog_prerequisite_post on Post {\n id\n creator {\n id\n __typename\n }\n collection {\n id\n name\n __typename\n }\n __typename\n}\n\nfragment PostResponses_post on Post {\n isPublished\n allowResponses\n isLimitedState\n ...PostResponsesContent_post\n __typename\n id\n}\n\nfragment PostPublishersInfoSection_post on Post {\n ...PostPublisherInfo_post\n __typename\n id\n}\n\nfragment UseSubscribeToAuthorOnScroll_post on Post {\n id\n mediumUrl\n ...SusiModal_post\n creator {\n id\n name\n ...SusiModal_user\n __typename\n }\n ...UseIsElligibleForSubscribeToAuthor_post\n __typename\n}\n"
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
|
|
79
|
+
host = ENV.fetch('MEDIUM_HOST', 'https://medium.com/_/graphql')
|
|
80
|
+
body = Request.body(Request.URL(host, method = 'POST', data = query));
|
|
68
81
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
previewImageFIleName = content&.dig(previewImage, "id")
|
|
82
|
+
if !body.nil?
|
|
83
|
+
json = JSON.parse(body)
|
|
72
84
|
|
|
73
|
-
|
|
85
|
+
postInfo = PostInfo.new()
|
|
86
|
+
postInfo.description = json&.dig(0, "data", "postResult", "previewContent", "subtitle")&.gsub(/[^[:print:]]/ , '')
|
|
87
|
+
postInfo.title = json&.dig(0, "data", "postResult", "title")&.gsub(/[^[:print:]]/ , '')
|
|
88
|
+
postInfo.tags = json&.dig(0, "data", "postResult", "tags").map{ |tag| tag["normalizedTagSlug"] }
|
|
74
89
|
|
|
75
|
-
|
|
90
|
+
previewImageFIleName = json&.dig(0, "data", "postResult", "previewImage", "id")
|
|
91
|
+
if !previewImageFIleName.nil?
|
|
92
|
+
|
|
93
|
+
imagePathPolicy = PathPolicy.new(pathPolicy.getAbsolutePath(postID), pathPolicy.getRelativePath(postID))
|
|
94
|
+
|
|
95
|
+
absolutePath = imagePathPolicy.getAbsolutePath(previewImageFIleName)
|
|
76
96
|
|
|
77
|
-
|
|
97
|
+
miro_host = ENV.fetch('MIRO_MEDIUM_HOST', 'https://miro.medium.com')
|
|
98
|
+
imageURL = "#{miro_host}/#{previewImageFIleName}"
|
|
78
99
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
100
|
+
if ImageDownloader.download(absolutePath, imageURL)
|
|
101
|
+
relativePath = imagePathPolicy.getRelativePath(previewImageFIleName)
|
|
102
|
+
postInfo.previewImage = relativePath
|
|
103
|
+
end
|
|
82
104
|
end
|
|
83
|
-
end
|
|
84
105
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
106
|
+
creatorName = json&.dig(0, "data", "postResult", "creator", "name")
|
|
107
|
+
if !creatorName.nil?
|
|
108
|
+
postInfo.creator = creatorName
|
|
109
|
+
end
|
|
89
110
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
111
|
+
colletionRef = json&.dig(0, "data", "postResult", "collection", "name")
|
|
112
|
+
if !colletionRef.nil?
|
|
113
|
+
postInfo.collectionName = colletionRef
|
|
114
|
+
end
|
|
94
115
|
|
|
95
|
-
|
|
116
|
+
|
|
96
117
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
118
|
+
firstPublishedAt = json&.dig(0, "data", "postResult", "firstPublishedAt")
|
|
119
|
+
if !firstPublishedAt.nil?
|
|
120
|
+
postInfo.firstPublishedAt = Time.at(0, firstPublishedAt, :millisecond)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
latestPublishedAt = json&.dig(0, "data", "postResult", "latestPublishedAt")
|
|
124
|
+
if !latestPublishedAt.nil?
|
|
125
|
+
postInfo.latestPublishedAt = Time.at(0, latestPublishedAt, :millisecond)
|
|
126
|
+
end
|
|
101
127
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
128
|
+
postInfo
|
|
129
|
+
else
|
|
130
|
+
nil
|
|
105
131
|
end
|
|
106
132
|
|
|
107
|
-
postInfo
|
|
108
133
|
end
|
|
109
134
|
end
|
data/lib/Request.rb
CHANGED
|
@@ -40,7 +40,6 @@ class Request
|
|
|
40
40
|
|
|
41
41
|
if method.upcase == "GET"
|
|
42
42
|
request = Net::HTTP::Get.new(uri)
|
|
43
|
-
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';
|
|
44
43
|
else
|
|
45
44
|
request = Net::HTTP::Post.new(uri)
|
|
46
45
|
request['Content-Type'] = 'application/json'
|
|
@@ -49,6 +48,8 @@ class Request
|
|
|
49
48
|
end
|
|
50
49
|
end
|
|
51
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
|
+
|
|
52
53
|
cookiesString = $cookies.reject { |_, value| value.nil? }
|
|
53
54
|
.map { |key, value| "#{key}=#{value}" }
|
|
54
55
|
.join("; ");
|
|
@@ -90,8 +91,6 @@ class Request
|
|
|
90
91
|
response = self.URL(location, method, data, retryCount)
|
|
91
92
|
end
|
|
92
93
|
end
|
|
93
|
-
|
|
94
|
-
puts response.read_body
|
|
95
94
|
|
|
96
95
|
response
|
|
97
96
|
end
|
data/lib/User.rb
CHANGED
|
@@ -10,16 +10,23 @@ class User
|
|
|
10
10
|
username = username[1...]
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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")
|
data/lib/ZMediumFetcher.rb
CHANGED
|
@@ -140,14 +140,7 @@ class ZMediumFetcher
|
|
|
140
140
|
progress.message = "Downloading Post..."
|
|
141
141
|
progress.printLog()
|
|
142
142
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
postContent = Post.parsePostContentFromHTML(postHtml)
|
|
146
|
-
if postContent.nil?
|
|
147
|
-
raise "Error: Content is empty! PostURL: #{postURL}"
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
postInfo = Post.parsePostInfoFromPostContent(postContent, postID, imagePathPolicy)
|
|
143
|
+
postInfo = Post.parsePostInfo(postID, imagePathPolicy)
|
|
151
144
|
contentInfo = Post.fetchPostParagraphs(postID)
|
|
152
145
|
|
|
153
146
|
if contentInfo.nil?
|
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.
|
|
4
|
+
version: 2.6.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- ZhgChgLi
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2025-12-
|
|
10
|
+
date: 2025-12-15 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: nokogiri
|