NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Livejasmin, Add button for saving chatlog // @description Adds a button to the top left of the page that, when pressed, alerts the current contents of the chat window. // @version 2 // @license MIT // @copyright 2018, kompisn90 (https://openuserjs.org/users/kompisn90) // @include https://*.livejasmin.com/* // @include https://*.jasmin.com/* // @include https://livejasmin.com/* // @include https://jasmin.com/* // @exclude https://www.livejasmin.com/en/member/favourite/get-favourite-list // @require https://cdn.jsdelivr.net/npm/vue/dist/vue.js // @grant GM.setValue // @grant GM.getValue // ==/UserScript== const getModelName = url => { let splits = [ 'html5/', 'chat/' ] return url.split(splits.find(split => url.indexOf(split) > -1))[1] } const main = async () => { let modelName = getModelName(window.location.href) if (!modelName) { return } if (!models.includes(modelName)) { models.push(modelName) GM.setValue('models', JSON.stringify(models)) } let storedLog = await GM.getValue(modelName, '') storedLog = storedLog.split('\n') let newLog = getNewLog(); let completeLog = concatenate(storedLog, newLog, 5) console.log(completeLog) return await storeLog(modelName, completeLog) } const getNewLog = () => { return Array.from(document.querySelectorAll('ul.chat_flow li')).map(m => m.textContent.trim()) } const storeLog = async (model, log) => { return await GM.setValue(model, log.join('\n')) } const concatenate = (arr1, arr2) => { if (arr2.filter(line => line === arr1[arr1.length - 1]).length > 0) { arr2.reverse() let arr2index = arr2.length - arr2.findIndex(line => line === arr1[arr1.length - 1]) arr2.reverse() let perfectMatch = true let appendIndex = arr1.length for (let i = 1; i <= arr1.length; i++) { if (arr1[arr1.length - i] === arr2[arr2index - i] && perfectMatch) { appendIndex = arr1.length - i } else { perfectMatch = false } } return arr1.slice(0, appendIndex).concat(arr2) } return arr1.concat(arr2) } var settingsCounterTimeout = 0 const whenSettings = cb => { let settings = document.querySelector('#ext-gen33') if (!settings && settingsCounterTimeout < 100) { settingsCounterTimeout++ setTimeout(() => whenSettings(cb), 100) } else { cb() } } const render = arr => { return '<pre>' + arr.join('\n') + '</pre>' } const getChatlog = async () => { let models = await GM.getValue('models', '[]') return JSON.parse(models) } const style = /*html*/` <style scoped> #close { position: fixed; top: 0; right: 0; z-index: 99999; } .models { margin: 2em auto; text-align: center } .chat { width: 30vw; margin: 5em auto; color: rgb(123, 131, 141); padding: 2em; background-color: rgba(0, 0, 0, 0.8); } .chat li { margin-bottom: 5px; } .chat .model { color: #fc0; } .chat .user { color: white; } .chat .introduction { margin-top: 10px; border-top: 2px solid white; padding-top: 10px; } </style> ` const template = /*html*/` <ul v-if="log.length === 0" class="models"> <input v-model="search"> <li v-for="model in models" :key="model" :key="model"> <a href="javascript:void(0)" @click="showlog(model)"> {{ model }} </a> </li> </ul> <ul v-else class="chat"> <li v-for="(message, index) in log" :key="index" :class="{ 'model': message.toLowerCase().indexOf(selectedModel.toLowerCase()) === 0, 'user': message.indexOf(user) === 0, 'introduction': message.indexOf('Hi ') === 0, }"> {{ message }} </li> </ul> <button id="close" @click="close">X</button> ` var app const showChatlog = async () => { const appWrapper = document.createElement('div') appWrapper.innerHTML = style const appEl = document.createElement('div') appEl.innerHTML = template appEl.id = 'theApp' appWrapper.appendChild(appEl) let log = await getChatlog() document.body.innerHTML = appWrapper.outerHTML app = new Vue({ el: '#theApp', data: { modelList: log, selectedModel: '', log: [], search: '', user: 'Me : ', }, methods: { async showlog (model) { this.selectedModel = model let log = await GM.getValue(model, JSON.stringify(this.log.join('\n'))) log = log.split('\n') this.log = log }, close () { this.log = [] this.selectedModel = '' } }, mounted () { console.log('hello world from vue') }, computed: { models () { return this.modelList .filter(name => name.toLowerCase().indexOf(this.search.toLowerCase()) > -1) .sort((a, b) => a.localeCompare(b)) } } }) } whenSettings(() => { let settings = document.querySelector('#ext-gen33') let chatlog = settings.cloneNode(true) chatlog.id = '' chatlog.dataset.action = '' chatlog.children[0].href = 'javascript:void(0)' chatlog.children[0].innerHTML = 'Chatlog' chatlog.addEventListener('click', showChatlog) settings.parentNode.insertBefore(chatlog, settings.nextSibling) }) let models = [] ;(async () => { models = await GM.getValue('models', JSON.stringify(models)) models = JSON.parse(models) })(); let b = document.createElement('button') b.innerHTML = 'Save chatlog' b.style.position = 'fixed' b.style.top = '0px' b.style.left = '0px' b.style.zIndex = '9999999' document.body.appendChild(b) b.addEventListener('click', async () => { main() }) setInterval(async () => { main() }, 30000)