App-phoebe

 view release on metacpan or  search on metacpan

lib/App/Phoebe/Ijirait.pm  view on Meta::CPAN

  } } );

sub init {
  my $next = 1;
  $data = {
    people => [
      {
	id => $next++, # 1
	name => "Ijiraq",
	description => "A shape-shifter with red eyes.",
	fingerprint => "",
	location => $next, # 2
	ts => time,
      } ],
    rooms => [
      {
	id => $next++, # 2
	name => "The Tent",
	description => "This is a large tent, illuminated by candles.",
	exits => [
	  {
	    id => $next++, # 3
	    name => "An exit leads outside.",
	    direction => "out",
	    destination => $next,
	  } ],
	things => [],
	words => [
	  {
	    text => "Welcome!",
	    by => 1, # Ijirait
	    ts => time,
	  } ],
      },
      {
	id => $next++, # 4
	name => "Outside The Tent",
	description => "You’re standing in a rocky hollow, somewhat protected from the wind. There’s a large tent, here.",
	exits => [
	  {
	    id => $next++, # 5
	    name => "A tent flap leads inside.",
	    direction => "tent",
	    destination => 2, # The Tent
	  } ],
      	things => [],
	words => [],
      } ] };
  $data->{next} = $next;
};

# Save the world every half hour.
Mojo::IOLoop->recurring(1800 => \&save_world);

# Streaming needs a special handler because the stream never closes.
unshift(@request_handlers, "^gemini://(?:$host)(?:\\d+)?/play/ijirait/stream" => \&add_streamer);

sub add_streamer {
  my $stream = shift;
  my $data = shift;
  $log->debug("Handle streaming request");
  $log->debug("Discarding " . length($data->{buffer}) . " bytes")
      if $data->{buffer};
  my $url = $data->{request};
  my $port = App::Phoebe::port($stream);
  if ($url =~ m!^(?:gemini:)?//($host)(?::$port)?/play/ijirait/stream$!) {
    my $p = login($stream);
    if ($p) {
      # 1h timeout
      $stream->timeout(3600);
      # remove from channel members if an error happens
      $stream->on(close => sub { my $stream = shift; logout($stream, $p, "Connection closed") });
      $stream->on(error => sub { my ($stream, $err) = @_; logout($stream, $p, $err) });
      push(@streamers, { stream => $stream, person => $p });
      success($stream);
      $stream->write(encode_utf8 "# Streaming $p->{name}\n");
      $stream->write(encode_utf8 "Make sure you connect to game using a different client "
		     . "(with the same client certificate!) in order to play $p->{name}.\n");
      $stream->write(encode_utf8 "=> /play/ijirait Play $p->{name}.");
      # don't close the stream!
    } else {
      $stream->close_gracefully();
    }
  } else {
    result($stream, "59", "Don't know how to handle $url");
    $stream->close_gracefully();
  }
}

sub logout {
  my ($stream, $p, $msg) = @_;
  $log->debug("Disconnected $p->{name}: $msg");
  @streamers = grep { $_->{stream} ne $stream and $_->{person} ne $p } @streamers;
}

# run every minute and print a timestamp every 5 minutes
Mojo::IOLoop->recurring(60 => sub {
  my $loop = shift;
  my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime(time);
  return unless $min % 5 == 0;
  return unless @streamers > 0;
  $log->debug("Ijirait streamer ping");
  my $ts = sprintf("%02d:%02d UTC\n", $hour, $min);
  for (@streamers) {
      $_->{stream}->write($ts);
  }});

# notify every streamer in the same room
sub notify {
  my ($p, $msg) = @_;
  eval {
    for my $s (grep { $_->{person}->{location} == $p->{location} } @streamers) {
      my $stream = $s->{stream};
      next unless $stream;
      $stream->write(encode_utf8 $msg);
      $stream->write("\n");
    }
  };
  $log->error("Error notifying people of '$msg': $@") if $@;
}



( run in 2.303 seconds using v1.01-cache-2.11-cpan-8f98c5d2c55 )