Skip to content

Instantly share code, notes, and snippets.

@serverglitch
Created October 25, 2022 02:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save serverglitch/36d47ff41bcf8d6d45dc8c13a100c5ab to your computer and use it in GitHub Desktop.
Save serverglitch/36d47ff41bcf8d6d45dc8c13a100c5ab to your computer and use it in GitHub Desktop.
Open Scenes Hack
// ares-webportal/app/controllers/scenes-open.js
import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
import AuthenticatedController from 'ares-webportal/mixins/authenticated-controller';
export default Controller.extend(AuthenticatedController, {
gameApi: service(),
gameSocket: service(),
flashMessages: service(),
newActivity: false,
onSceneActivity: function (type, msg, timestamp) {
let splitMsg = msg.split('|');
let sceneId = splitMsg[0];
let lastPosed = splitMsg[1];
let model = this.get('model.active');
model.forEach((s, i) => {
if (s.id === sceneId) {
this.set(`model.active.${i}.is_unread`, true);
this.set(`model.active.${i}.updated`, timestamp);
this.set(`model.active.${i}.last_posed`, lastPosed);
}
});
},
resetOnExit: function () {
this.set('newActivity', false);
},
setupCallback: function () {
let self = this;
this.gameSocket.setupCallback(
'new_scene_activity',
function (type, msg, timestamp) {
self.onSceneActivity(type, msg, timestamp);
}
);
},
actions: {
refresh() {
this.set('newActivity', false);
this.send('reloadModel');
},
joinScene(id) {
let api = this.gameApi;
api.requestOne('joinScene', { id: id }, null).then((response) => {
if (response.error) {
return;
}
this.flashMessages.success('You join the scene.');
this.send('reloadModel');
});
},
stopWatching(id) {
let api = this.gameApi;
api.requestOne('unwatchScene', { id: id }, null).then((response) => {
if (response.error) {
return;
}
this.flashMessages.success('You are no longer watching that scene.');
this.send('reloadModel');
});
},
watchScene(id) {
let api = this.gameApi;
api.requestOne('watchScene', { id: id }, null).then((response) => {
if (response.error) {
return;
}
this.flashMessages.success('You start watching that scene.');
this.send('reloadModel');
});
},
},
});
# aresmush/plugins/scenes/web/open_scenes_handler.rb
module AresMUSH
module Scenes
class OpenScenesRequestHandler
def handle(request)
enactor = request.enactor
error = Website.check_login(request, true)
return error if error
open_scenes = Scene.all.select { |s| !s.completed && Scenes.can_read_scene?(enactor, s) }
.sort { |s1, s2| sort_scene(s1, s2, enactor) }
.map { |s| scene_data(s, enactor) }
if (enactor)
unshared = enactor.unshared_scenes.sort_by { |s| s.id.to_i }.reverse.map { |s| {
title: s.date_title,
people: s.participant_names.join(' '),
id: s.id }}
else
unshared = nil
end
{
active: open_scenes,
unshared: unshared,
unshared_deletion_days: Global.read_config('scenes', 'unshared_scene_deletion_days')
}
end
def scene_data(s, enactor)
{
id: s.id,
title: s.title,
summary: (can_read?(enactor, s) && !s.summary.blank?) ? Website.format_markdown_for_html(s.summary) : nil,
content_warning: s.content_warning,
limit: s.limit,
location: Scenes.can_read_scene?(enactor, s) ? s.location : t('scenes.private'),
icdate: s.icdate,
can_view: enactor && Scenes.can_read_scene?(enactor, s),
is_private: s.private_scene,
participants: Scenes.participants_and_room_chars(s)
.select { |p| !p.who_hidden }
.sort_by { |p| p.name }
.map { |p| {
name: p.name,
nick: p.nick,
id: p.id,
icon: Website.icon_for_char(p),
status: Website.activity_status(p),
online: Login.is_online?(p),
last_posed: s.last_posed == p }},
scene_type: s.scene_type ? s.scene_type.titlecase : 'Unknown',
scene_pacing: s.scene_pacing,
likes: s.likes,
is_unread: can_read?(enactor, s) && enactor && s.participants.include?(enactor) && s.is_unread?(enactor),
updated: can_read?(enactor, s) ? OOCTime.local_long_timestr(enactor, s.last_activity) : nil,
watching: Scenes.is_watching?(s, enactor),
participating: Scenes.is_participant?(s, enactor),
last_posed: can_read?(enactor, s) && s.last_posed ? s.last_posed.name : nil,
last_pose_time_str: s.last_pose_time_str(enactor)
}
end
def can_read?(enactor, s)
Scenes.can_read_scene?(enactor, s)
end
def sort_scene(s1, s2, enactor)
if (Scenes.is_participant?(s2, enactor) && !Scenes.is_participant?(s1, enactor))
return 1
end
if (Scenes.is_participant?(s1, enactor) && !Scenes.is_participant?(s2, enactor))
return -1
end
if (!s1.private_scene && s2.private_scene)
return -1
end
if (s1.private_scene && !s2.private_scene)
return 1
end
if (s1.updated_at < s2.updated_at)
return 1
end
if (s2.updated_at < s1.updated_at)
return -1
end
return 0
end
end
end
end
// ares-webportal/app/routes/scenes-open.js
import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';
import DefaultRoute from 'ares-webportal/mixins/default-route';
import ReloadableRoute from 'ares-webportal/mixins/reloadable-route';
import RouteResetOnExit from 'ares-webportal/mixins/route-reset-on-exit';
export default Route.extend(DefaultRoute, ReloadableRoute, RouteResetOnExit, {
gameApi: service(),
gameSocket: service(),
activate: function () {
this.controllerFor('scenes-open').setupCallback();
},
deactivate: function () {
this.gameSocket.removeCallback('new_scene_activity');
},
model: function () {
let api = this.gameApi;
return api.requestOne('openScenes');
},
});
// ares-webportal/app/router.js
...
this.route('scenes-open');
...
//----------------------------
ares-webportal/app/templates/scenes-open.hbs
//----------------------------
{{page-title "Open Scenes"}}
<h1>Open Scenes</h1>
<p>This list shows scenes that are currently in progress and open. You can play with a MUSH client or through the web
portal.</p>
<p>The unread flags <span class="badge rounded-pill bg-primary"> <i class="fa fa-flag"
aria-label="New Activity Flag"></i></span> show new activity in public scenes or scenes you're
watching/participating in.</p>
{{#if this.isApproved}}
<div class="action-buttons">
<LinkTo @route="scene-create" class="btn btn-secondary">Create Scene</LinkTo>
<LinkTo @route="play" class="btn btn-primary">Play</LinkTo>
</div>
{{/if}}
{{#each this.model.active as |scene| }}
<div class="live-scenes-block">
<div class="row live-scenes-heading">
<div class="col col-xs-12 col-sm-6">
{{#if scene.is_unread}}
<span class="badge rounded-pill bg-primary"> <i class="fa fa-flag" aria-label="New Activity"></i></span>
{{/if}}
<LinkTo @route="scene-live" @model={{scene.id}} class="scene-title">
{{scene.id}} -
{{#if scene.title}}
{{scene.location}} - {{scene.title}}
{{else}}
{{scene.location}}
{{/if}}
{{#if scene.content_warning}}
<ContentWarningTag @warning={{scene.content_warning}} @position="top" />
{{/if}}
</LinkTo>
</div>
<div class="col col-xs-12 col-sm-4">
<ScenePrivacyTag @scene={{scene}} />
<ScenePacingTag @scene={{scene}} />
<SceneTypeTag @scene={{scene}} />
</div>
<div class="col col-xs-12 col-sm-2">
<div class="live-scenes-controls">
{{#if scene.watching}}
<a href="#" {{action 'stopWatching' scene.id}}><i class="fa fa-eye-slash" aria-label="Stop Watching"></i></a>
{{else}}
{{#if scene.can_view}}
<a href="#" {{action 'watchScene' scene.id}}><i class="fa fa-eye" aria-label="Watch"></i></a>
{{#if (not scene.participating) }}
<a href="#" {{action 'joinScene' scene.id}}><i class="fa fa-sign-in-alt" aria-label="Join"></i></a>
{{/if}}
{{/if}}
{{/if}}
</div>
</div>
</div>
<div class="row">
<div class="col col-xs-12 col-sm-9">
<div class="live-scenes-contents">
<div class="live-scenes-participants">
{{#each scene.participants as |char|}}
<CharIconInline @char={{char}} />
{{/each}}
</div>
{{#if scene.limit}}
<div><span class="scene-info-label">Notes:</span> {{scene.limit}}</div>
{{/if}}
{{#if scene.summary}}
<div class="scene-summary">
<a data-bs-toggle="collapse" href="#details-{{scene.id}}" class="">
<i class="fa fa-caret-down" aria-label="Details"></i> Show Details
</a>
<div id="details-{{scene.id}}" class="card-collapse collapse">
<p>
<AnsiFormat @text={{scene.summary}} />
</p>
</div>
</div>
{{/if}}
</div>
</div>
<div class="col col-xs-12 col-sm-3">
<div>
<span class="scene-info-label">Last:</span>
{{#if scene.last_posed}}
{{scene.last_posed}},
{{/if}}
{{scene.last_pose_time_str}}
</div>
<div>
<span class="scene-info-label">Date:</span> {{scene.icdate}}
</div>
</div>
</div>
</div>
{{/each}}
{{#if this.model.unshared}}
<br>
<hr>
<div class="alert alert-info">
<p>You have <LinkTo @route="scenes-unshared">unshared scenes</LinkTo>. Share or download them before they time out.
</p>
<p>
<LinkTo @route="scenes-unshared">View Unshared Scenes</LinkTo>
</p>
</div>
{{/if}}
{{outlet}}
# aresmush/plugins/scenes/scenes.rb
...
when "openScenes"
return OpenScenesRequestHandler
...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment