Class: Tempest::REPL::Runner

Inherits:
Object
  • Object
show all
Defined in:
lib/tempest/repl/runner.rb

Constant Summary collapse

PROMPT =
"tempest> ".freeze
HELP_TEXT =
<<~HELP
  Available commands:
    :timeline       Fetch and print the home timeline
    :stream on|off  Toggle the Jetstream live feed
    :open $XX|$LX   Open the post or URL with the given id in the browser
    :fav $XX        Like the post with id $XX
    :relogin        Re-authenticate when the cached session is dead
    :help           Show this help
    :quit           Exit tempest (or Ctrl-D)

    $XX <text>      Reply to the post with id $XX

  Any other input is sent as a new post.
HELP
DEFAULT_OPENER =
->(url) { system("open", url) }
RELOGIN_HINT =
"type :relogin to re-authenticate".freeze

Instance Method Summary collapse

Constructor Details

#initialize(session:, client:, input:, output:, dispatcher: Dispatcher.new, stream_manager: nil, handle_resolver: nil, stream_output: nil, timeline_store: nil, registry: Registry.new, opener: DEFAULT_OPENER, avatar_store: nil, reauth: nil) ⇒ Runner

Returns a new instance of Runner.



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/tempest/repl/runner.rb', line 35

def initialize(session:, client:, input:, output:, dispatcher: Dispatcher.new,
               stream_manager: nil, handle_resolver: nil, stream_output: nil,
               timeline_store: nil, registry: Registry.new, opener: DEFAULT_OPENER,
               avatar_store: nil, reauth: nil)
  @session = session
  @client = client
  @input = input
  @output = output
  @stream_output = stream_output || output
  @dispatcher = dispatcher
  @stream_manager = stream_manager
  @handle_resolver = handle_resolver
  @timeline_store = timeline_store
  @registry = registry
  @opener = opener
  @avatar_store = avatar_store
  @reauth = reauth
  # URIs already printed via bootstrap_timeline or backfill_timeline.
  # Jetstream's cursor-replay can re-emit those same posts on startup
  # (the persisted cursor is older than the getTimeline window), so the
  # stream handler skips post events whose URI is in this set.
  @displayed_post_uris = Set.new
end

Instance Method Details

#auto_start_streamObject



81
82
83
84
85
86
# File 'lib/tempest/repl/runner.rb', line 81

def auto_start_stream
  return unless @stream_manager
  return if @stream_manager.running?

  @stream_manager.start { |event| handle_stream_event(event) }
end

#bootstrap_timelineObject



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/tempest/repl/runner.rb', line 59

def bootstrap_timeline
  return unless @timeline_store

  cached = @timeline_store.load
  cached_posts = cached ? Array(cached[:posts]) : []
  cached_posts.each { |post| print_post(post) }

  cached_uris = cached_posts.map(&:uri).to_set
  begin
    fetched = Timeline.fetch(@client)
  rescue Tempest::Error => e
    @output.puts "-- timeline fetch failed: #{e.message}"
    return
  end

  new_posts = fetched.reject { |post| cached_uris.include?(post.uri) }
  new_posts.reverse_each { |post| print_post(post) }

  merged = cached_posts + new_posts.reverse
  @timeline_store.save(posts: merged)
end

#runObject



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/tempest/repl/runner.rb', line 88

def run
  loop do
    line = read_line
    command = @dispatcher.dispatch(line)

    case command.name
    when :quit
      @stream_manager&.stop
      @output.puts "bye."
      break
    when :noop
      next
    when :help
      @output.puts HELP_TEXT
    when :timeline
      handle_timeline
    when :stream
      handle_stream(command.args.first)
    when :post
      handle_post(command.args.first)
    when :reply
      handle_reply(command.args[0], command.args[1])
    when :open
      handle_open(command.args.first)
    when :fav
      handle_fav(command.args.first)
    when :relogin
      handle_relogin
    when :unknown
      @output.puts "unknown command: :#{command.args.first}"
    end
  end
end