bad_pigeon 0.1.2 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c3f86a627c1ab2f039167161fe3ecfbeb3db6d96a925673c23165cf74a3cc54b
4
- data.tar.gz: f43ac43250395cc7f9200c5cc8bcc2bb2596827aac61f88110e078ae0210fa64
3
+ metadata.gz: f61588b2b5fe681fc476d917a97f4aa034472577d7f522726eb1da3f52fea5ba
4
+ data.tar.gz: 00f842e06596ba7272c8ceebcaca18db7d05f405d461469b4aa87eb0a73fae73
5
5
  SHA512:
6
- metadata.gz: 7c02d9d1fe34e0c97a05d0135db11fef8dc401261fd1f2c1fa7a3cd961d191e547e2e462b7792728ac602a5567db8c756f2f2f6906ff9308cdbd8a2cdf53be34
7
- data.tar.gz: 8eb675eb61e1c2bfb9ace4e21b2aa2526fd878933eedcb48798b892d9261f80d82ce47b765a7b25a1911c9c6586cc899e16a8160ccb18d1d12cfb2b93d43cb96
6
+ metadata.gz: 8e27114293d1265fc4e0fb8efa51755c5f362665e138ebb074068073b45aa5fb2a227b92a2a5b707fd45e25c81f683634b49debb965dab1750444aff4c56b9c2
7
+ data.tar.gz: 66a40d6e5e6725a50f3d50157b856d751e5fa0c6b7e44b81dde9ab6ee9e70e0c00f364ce7d1e0e7323e2d1b7e877dd959ef9728b8c5ffad41665579c7424084c
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## [0.1.4] - 2023-09-17
2
+
3
+ - compatibility fixes
4
+
5
+ ## [0.1.3] - 2023-09-08
6
+
7
+ - fixed handling of quotes of deleted posts
8
+ - compatibility fixes for latest changes in the tweet response structure
9
+
1
10
  ## [0.1.2] - 2023-07-11
2
11
 
3
12
  - fixed issue with some requests being ignored because they use POST method
@@ -2,12 +2,17 @@ module BadPigeon
2
2
  module Component
3
3
  # normal tweet in e.g. home/latest or a user's timeline
4
4
  ORGANIC_FEED_TWEET = "suggest_ranked_organic_tweet"
5
+ NORMAL_TWEET = "tweet"
6
+
7
+ # tweet in the latest timeline
8
+ FOLLOWING = "following_in_network"
5
9
 
6
10
  # tweet in a list timeline
7
11
  ORGANIC_LIST_TWEET = "suggest_organic_list_tweet"
8
12
 
9
- # user's pinned tweet
13
+ # user's pinned tweets
10
14
  PINNED_TWEET = "suggest_pinned_tweet"
15
+ PINNED_TWEETS = "pinned_tweets"
11
16
 
12
17
  # reply that shows up in your timeline
13
18
  EXTENDED_REPLY = "suggest_extended_reply"
@@ -19,6 +24,7 @@ module BadPigeon
19
24
 
20
25
  # promoted tweet (ad)
21
26
  PROMOTED_TWEET = "suggest_promoted"
27
+ FOLLOWING_PROMOTED = "following_promoted"
22
28
 
23
29
  # "Who to follow" block
24
30
  FOLLOW_SUGGESTIONS = "suggest_who_to_follow"
@@ -2,6 +2,13 @@ require 'bad_pigeon/elements/timeline_tweet'
2
2
  require 'bad_pigeon/util/assertions'
3
3
 
4
4
  module BadPigeon
5
+
6
+ # Represents an "entry" which is a part of a timeline response. An entry in most cases is a wrapper for either one
7
+ # tweet or a group of connected tweets (e.g. a parent and a reply).
8
+ #
9
+ # Tweets can be extracted from an entry using ({#items}) method, which returns an array of tweets as instances of
10
+ # {BadPigeon::TimelineTweet} class.
11
+
5
12
  class TimelineEntry
6
13
  include Assertions
7
14
 
@@ -2,6 +2,12 @@ require 'bad_pigeon/elements/timeline_entry'
2
2
  require 'bad_pigeon/util/assertions'
3
3
 
4
4
  module BadPigeon
5
+
6
+ # Represents an "instruction" which is a part of a timeline response. An instruction can be e.g. pinning one entry
7
+ # to the top or adding some number of entries to the list view.
8
+ #
9
+ # A timeline includes one or more "entries" ({BadPigeon::TimelineEntry}), most of which contain one or more tweets.
10
+
5
11
  class TimelineInstruction
6
12
  include Assertions
7
13
 
@@ -2,6 +2,12 @@ require 'bad_pigeon/models/tweet'
2
2
  require 'bad_pigeon/util/assertions'
3
3
 
4
4
  module BadPigeon
5
+
6
+ # Represents a single tweet in a timeline (may possibly include no data in some cases).
7
+ #
8
+ # Use the {#tweet} method to get an instance of {BadPigeon::Tweet}, which is the final tweet model from which you can
9
+ # extract specific fields or a properly formatted JSON representation.
10
+
5
11
  class TimelineTweet
6
12
  include Assertions
7
13
 
@@ -9,26 +15,8 @@ module BadPigeon
9
15
  @json = json
10
16
  end
11
17
 
12
- def result_type
13
- @json['tweet_results']['result'] && @json['tweet_results']['result']['__typename']
14
- end
15
-
16
- def tweet_data
17
- case result_type
18
- when 'Tweet', 'TweetWithVisibilityResults'
19
- @json['tweet_results']['result']
20
- when 'TweetUnavailable'
21
- nil
22
- when nil
23
- nil
24
- else
25
- assert("Unknown tweet result type: #{result_type}")
26
- nil
27
- end
28
- end
29
-
30
18
  def tweet
31
- tweet_data && Tweet.new(tweet_data)
19
+ @json['tweet_results']['result'] && Tweet.from_result(@json['tweet_results']['result'])
32
20
  end
33
21
  end
34
22
  end
@@ -9,7 +9,10 @@ module BadPigeon
9
9
  case entry.component
10
10
  when Component::ORGANIC_FEED_TWEET,
11
11
  Component::ORGANIC_LIST_TWEET,
12
+ Component::NORMAL_TWEET,
13
+ Component::FOLLOWING,
12
14
  Component::PINNED_TWEET,
15
+ Component::PINNED_TWEETS,
13
16
  Component::EXTENDED_REPLY,
14
17
  Component::SOCIAL_CONTEXT,
15
18
  Component::SOCIAL_ACTIVITY,
@@ -17,6 +20,7 @@ module BadPigeon
17
20
  then true
18
21
 
19
22
  when Component::PROMOTED_TWEET,
23
+ Component::FOLLOWING_PROMOTED,
20
24
  Component::FOLLOW_SUGGESTIONS
21
25
  then false
22
26
 
@@ -2,6 +2,11 @@ require_relative 'har_request'
2
2
  require 'json'
3
3
 
4
4
  module BadPigeon
5
+
6
+ # Represents a whole request archive bundle loaded from a *.har file.
7
+ #
8
+ # An archive consists of some number of requests ({BadPigeon::HARRequest}).
9
+
5
10
  class HARArchive
6
11
  def initialize(data)
7
12
  @json = JSON.parse(data)
@@ -2,6 +2,15 @@ require 'addressable/uri'
2
2
  require 'json'
3
3
 
4
4
  module BadPigeon
5
+
6
+ # Represents info about one request and response to it, including the complete response data ({#response_body},
7
+ # or {#response_json} for a parsed JSON form).
8
+ #
9
+ # Requests that may potentially include tweet data return true from the {#includes_tweet_data?} method. The JSON
10
+ # data from each such request represents a "timeline" and may be parsed using a specific timeline class like
11
+ # {BadPigeon::HomeTimeline} or {BadPigeon::UserTimeline}; the {BadPigeon::TIMELINE_TYPES} hash provides a mapping
12
+ # of GraphQL endpoint names to timeline classes, and the endpoint name can be read using {#endpoint_name} method.
13
+
5
14
  class HARRequest
6
15
  def initialize(json)
7
16
  @json = json
@@ -6,11 +6,29 @@ require 'bad_pigeon/util/strict_hash'
6
6
  require 'time'
7
7
 
8
8
  module BadPigeon
9
+
10
+ #
11
+ # A model that represents one tweet with an interface matching that from the original `twitter` Ruby gem.
12
+ #
13
+
9
14
  class Tweet
10
15
  include Assertions
16
+ extend Assertions
11
17
 
12
18
  attr_reader :json
13
19
 
20
+ def self.from_result(json)
21
+ case json['__typename']
22
+ when 'Tweet', 'TweetWithVisibilityResults'
23
+ Tweet.new(json)
24
+ when nil, 'TweetUnavailable', 'TweetTombstone'
25
+ nil
26
+ else
27
+ assert("Unknown tweet result type: #{json['__typename']}")
28
+ nil
29
+ end
30
+ end
31
+
14
32
  def initialize(json)
15
33
  case json['__typename']
16
34
  when 'Tweet'
@@ -50,17 +68,18 @@ module BadPigeon
50
68
  alias retweeted_status? retweet?
51
69
 
52
70
  def retweeted_status
53
- legacy['retweeted_status_result'] && Tweet.new(legacy['retweeted_status_result']['result'])
71
+ legacy['retweeted_status_result'] && Tweet.from_result(legacy['retweeted_status_result']['result'])
54
72
  end
55
73
 
56
74
  def quoted_status?
57
75
  # there is also legacy['is_quote_status'], but it may be true while quoted_status_result
58
76
  # is not set if the quoted status was deleted
59
- !!json['quoted_status_result']
77
+ !!quoted_status
60
78
  end
61
79
 
62
80
  def quoted_status
63
- json['quoted_status_result'] && Tweet.new(json['quoted_status_result']['result'])
81
+ qsr = json['quoted_status_result']
82
+ qsr && qsr['result'] && Tweet.from_result(qsr['result'])
64
83
  end
65
84
 
66
85
  alias quoted_tweet? quoted_status?
@@ -1,6 +1,11 @@
1
1
  require 'addressable/uri'
2
2
 
3
3
  module BadPigeon
4
+
5
+ #
6
+ # A model that represents a "URL entity" of a tweet (a shortened link with info about the shortened and original URL).
7
+ #
8
+
4
9
  class URLEntity
5
10
  def initialize(json)
6
11
  @json = json
@@ -1,4 +1,9 @@
1
1
  module BadPigeon
2
+
3
+ #
4
+ # A model that represents a user with an interface matching that from the original `twitter` Ruby gem.
5
+ #
6
+
2
7
  class User
3
8
  attr_reader :json
4
9
 
@@ -2,6 +2,12 @@ require 'bad_pigeon/elements/timeline_instruction'
2
2
  require 'bad_pigeon/util/assertions'
3
3
 
4
4
  module BadPigeon
5
+
6
+ # Represents a timeline response for user's "For You" or "Following" timeline.
7
+ #
8
+ # A timeline includes one or more "instructions" ({BadPigeon::TimelineInstruction}), and usually in particular a
9
+ # "TimelineAddEntries" instruction which provides one or more entries containing tweets.
10
+
5
11
  class HomeTimeline
6
12
  include Assertions
7
13
 
@@ -2,6 +2,12 @@ require 'bad_pigeon/elements/timeline_instruction'
2
2
  require 'bad_pigeon/util/assertions'
3
3
 
4
4
  module BadPigeon
5
+
6
+ # Represents a timeline response for a list timeline.
7
+ #
8
+ # A timeline includes one or more "instructions" ({BadPigeon::TimelineInstruction}), and usually in particular a
9
+ # "TimelineAddEntries" instruction which provides one or more entries containing tweets.
10
+
5
11
  class ListTimeline
6
12
  include Assertions
7
13
 
@@ -2,6 +2,12 @@ require 'bad_pigeon/elements/timeline_instruction'
2
2
  require 'bad_pigeon/util/assertions'
3
3
 
4
4
  module BadPigeon
5
+
6
+ # Represents a timeline response for a timeline of user's posts as seen on their profile page.
7
+ #
8
+ # A timeline includes one or more "instructions" ({BadPigeon::TimelineInstruction}), and usually in particular a
9
+ # "TimelineAddEntries" instruction which provides one or more entries containing tweets.
10
+
5
11
  class UserTimeline
6
12
  include Assertions
7
13
 
@@ -6,6 +6,10 @@ require_relative 'timelines'
6
6
  require 'uri'
7
7
 
8
8
  module BadPigeon
9
+
10
+ # The main entry point to the library. Pass the contents of a HAR archive file to {#get_tweets_from_har} and get
11
+ # a flat list of all extracted tweets in return.
12
+
9
13
  class TweetExtractor
10
14
  include Assertions
11
15
 
@@ -19,5 +19,9 @@ module BadPigeon
19
19
  end
20
20
  end
21
21
  end
22
+
23
+ def self.extended(target)
24
+ included(target.singleton_class)
25
+ end
22
26
  end
23
27
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BadPigeon
4
- VERSION = "0.1.2"
4
+ VERSION = "0.1.4"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bad_pigeon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kuba Suder
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-07-11 00:00:00.000000000 Z
11
+ date: 2023-10-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable