User:Sophivorus/chatbot.js
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
const Chatbot = {
init() {
const mainPage = mw.config.get( 'wgIsMainPage' );
if ( !mainPage ) {
return;
}
const action = mw.config.get( 'wgAction' );
if ( action !== 'view' ) {
return;
}
Chatbot.addIcon();
},
addIcon() {
const $chatbot = $( '<div id="appropedia-chatbot"></div>' );
const $icon = $( '<svg id="appropedia-chatbot-icon" xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 122.88 119.35" transform="scale(-1,1)"><path d="M57.49,29.2V23.53a14.41,14.41,0,0,1-2-.93A12.18,12.18,0,0,1,50.44,7.5a12.39,12.39,0,0,1,2.64-3.95A12.21,12.21,0,0,1,57,.92,12,12,0,0,1,61.66,0,12.14,12.14,0,0,1,72.88,7.5a12.14,12.14,0,0,1,0,9.27,12.08,12.08,0,0,1-2.64,3.94l-.06.06a12.74,12.74,0,0,1-2.36,1.83,11.26,11.26,0,0,1-2,.93V29.2H94.3a15.47,15.47,0,0,1,15.42,15.43v2.29H115a7.93,7.93,0,0,1,7.9,7.91V73.2A7.93,7.93,0,0,1,115,81.11h-5.25v2.07A15.48,15.48,0,0,1,94.3,98.61H55.23L31.81,118.72a2.58,2.58,0,0,1-3.65-.29,2.63,2.63,0,0,1-.63-1.85l1.25-18h-.21A15.45,15.45,0,0,1,13.16,83.18V81.11H7.91A7.93,7.93,0,0,1,0,73.2V54.83a7.93,7.93,0,0,1,7.9-7.91h5.26v-2.3A15.45,15.45,0,0,1,28.57,29.2H57.49ZM82.74,47.32a9.36,9.36,0,1,1-9.36,9.36,9.36,9.36,0,0,1,9.36-9.36Zm-42.58,0a9.36,9.36,0,1,1-9.36,9.36,9.36,9.36,0,0,1,9.36-9.36Zm6.38,31.36a2.28,2.28,0,0,1-.38-.38,2.18,2.18,0,0,1-.52-1.36,2.21,2.21,0,0,1,.46-1.39,2.4,2.4,0,0,1,.39-.39,3.22,3.22,0,0,1,3.88-.08A22.36,22.36,0,0,0,56,78.32a14.86,14.86,0,0,0,5.47,1A16.18,16.18,0,0,0,67,78.22,25.39,25.39,0,0,0,72.75,75a3.24,3.24,0,0,1,3.89.18,3,3,0,0,1,.37.41,2.22,2.22,0,0,1,.42,1.4,2.33,2.33,0,0,1-.58,1.35,2.29,2.29,0,0,1-.43.38,30.59,30.59,0,0,1-7.33,4,22.28,22.28,0,0,1-7.53,1.43A21.22,21.22,0,0,1,54,82.87a27.78,27.78,0,0,1-7.41-4.16l0,0ZM94.29,34.4H28.57A10.26,10.26,0,0,0,18.35,44.63V83.18A10.26,10.26,0,0,0,28.57,93.41h3.17a2.61,2.61,0,0,1,2.41,2.77l-1,14.58L52.45,94.15a2.56,2.56,0,0,1,1.83-.75h40a10.26,10.26,0,0,0,10.22-10.23V44.62A10.24,10.24,0,0,0,94.29,34.4Z"/></svg>' );
$icon.on( 'click', Chatbot.openChat );
$chatbot.append( $icon );
const chatbot = $chatbot[0];
document.body.append( chatbot );
},
openChat() {
mw.loader.using( '@wikimedia/codex' ).then( require => {
const Vue = require( 'vue' );
const Codex = require( '@wikimedia/codex' );
const app = Vue.createMwApp( Chatbot.chatComponent );
app.component( 'cdx-text-input', Codex.CdxTextInput );
const chatbot = this.parentElement;
app.mount( chatbot );
} );
},
chatComponent: {
template: `
<div id="appropedia-chatbot-chat">
<div id="appropedia-chatbot-history" v-if="history.length">
<div v-for="item in history" :class="item.type" v-html="item.text"></div>
</div>
<cdx-text-input id="appropedia-chatbot-input" v-model="input.value" :disabled="input.disabled" :placeholder="input.placeholder" @keydown="onKeydown"></cdx-text-input>
<div id="appropedia-chatbot-footer">
<a href="/Appropedia:Village_pump">Leave feedback</a>
</div>
</div>
`,
data() {
return {
input: {
value: '',
placeholder: 'Ask Appropedia...',
disabled: false
},
history: [],
session: null,
};
},
methods: {
onKeydown( event ) {
if ( event.key === 'Enter' ) {
this.send();
}
},
async send() {
const value = this.input.value;
// Update the interface
const inputItem = { type: 'input', text: value };
this.history.push( inputItem );
this.input.placeholder = 'Thinking...';
this.input.value = '';
this.input.disabled = true;
// Fetch the response
const body = {
message: value,
source_mode: 'none',
sources: [ 'appropedia' ],
session_id: this.session
};
const response = await fetch( 'https://disaster-clippy.up.railway.app/api/v1/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify( body )
} );
const data = await response.json();
let text = data.response;
text = text.replace( /\[(.*?)\]\((.*?)\)/g, '<a href="$2">$1</a>' );
text = text.replace( /\*\*(.*?)\*\*/g, '<em>$1</em>' );
text = text.replace( /\n/g, '<br>' );
// Save the session
this.session = data.session_id;
// Update the interface
const outputItem = { type: 'output', text: text };
this.history.push( outputItem );
this.input.disabled = false;
this.input.placeholder = 'Ask Appropedia...';
}
},
updated() {
const history = document.getElementById( 'appropedia-chatbot-history' );
history.scrollTop = history.scrollHeight;
const input = document.getElementById( 'appropedia-chatbot-input' );
input.focus();
}
}
};
mw.hook( 'wikipage.content' ).add( Chatbot.init );