Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions websites/M/Microsoft Copilot/Microsoft Copilot.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
{
"microsoftcopilot.aiResponding": {
"description": "Displayed when the AI is generating a response. {0} will be replaced with the AI's name. e.g., 'ChatGPT is responding...'",
"message": "Copilot is responding..."
},
"microsoftcopilot.conversationStats": {
"description": "Displayed to show the number of times the user asked a question and total words used, e.g., 'asked 3 times | 150 words'.",
"message": "asked {0} times | {1} words"
},
"microsoftcopilot.startNewConversation": {
"description": "Displayed when the user is starting a new conversation.",
"message": "Start new conversation"
},
"microsoftcopilot.talkingWithAI": {
"description": "Displayed when the user is engaging in a conversation with the AI. {0} will be replaced with the AI's name. e.g., 'Talking with ChatGPT about something'",
"message": "Talking with Copilot about something"
},
"microsoftcopilot.thinkingOfPrompt": {
"description": "Displayed when the user is thinking of a new prompt.",
"message": "Thinking of a new prompt..."
},
"microsoftcopilot.prompt": {
"description": "Displayed as a label for the user's prompt input. {0} will be replaced with the user's prompt. e.g., 'Prompt: How does AI work?'",
"message": "Prompt: {0}"
},
"microsoftcopilot.viewPublicImagesGenerated": {
"description": "Displayed as a link to view public images generated by the AI.",
"message": "View public images generated by Copilot"
},
"microsoftcopilot.unknown": {
"description": "Displayed when the information is unknown.",
"message": "Unknown"
},
"microsoftcopilot.listeningDayNews": {
"description": "Displayed when the user is listening to the day's news.",
"message": "Listening to the day's news"
},
"microsoftcopilot.writingPage": {
"description": "Displayed when the user is writing or editing a page.",
"message": "Writing or editing a page"
},
"microsoftcopilot.viewTheirLibrary": {
"description": "Displayed when the user is viewing their library.",
"message": "Viewing their library"
},
"microsoftcopilot.viewAGeneratedImage": {
"description": "Displayed when the user is viewing a generated image in their library.",
"message": "Viewing a generated image"
},
"microsoftcopilot.viewResearchReport": {
"description": "Displayed when the user is viewing a specific research report.",
"message": "Viewing research report:"
},
"microsoftcopilot.checkingWeather": {
"description": "Displayed when the user is checking the weather using Microsoft Copilot.",
"message": "Checking the weather in {0}"
},
"microsoftcopilot.watchingVideoArticle": {
"description": "Displayed when the user is watching a video article.",
"message": "Watching a video article"
},
"microsoftcopilot.discoverNews": {
"description": "Displayed when the user is discovering news articles.",
"message": "Discovering news articles"
},
"microsoftcopilot.discoverExperimentalFeatures": {
"description": "Displayed when the user is exploring experimental features in Microsoft Copilot Labs.",
"message": "Discovering experimental features"
},
"microsoftcopilot.generateAudioExpression": {
"description": "Displayed when the user is generating audio expressions in Microsoft Copilot Labs.",
"message": "Generating audio expression"
},
"microsoftcopilot.viewPublic3DGenerations": {
"description": "Displayed when the user is viewing public 3D generations in Microsoft Copilot Labs.",
"message": "Viewing public 3D generations"
},
"microsoftcopilot.viewTheir3DGenerations": {
"description": "Displayed when the user is viewing their own 3D generations in Microsoft Copilot Labs.",
"message": "Viewing their 3D generations"
},
"microsoftcopilot.playingWithAiGeneration": {
"description": "Displayed when the user is playing a game thanks to AI generation",
"message": "Playing thanks to AI generation"
}
}
40 changes: 40 additions & 0 deletions websites/M/Microsoft Copilot/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"$schema": "https://schemas.premid.app/metadata/1.15",
"apiVersion": 1,
"author": {
"id": "671037171611729920",
"name": "atom_skully"
},
"service": "Microsoft Copilot",
"description": {
"en": "Microsoft Copilot is your companion to inform, entertain and inspire. Get advice, feedback and straightforward answers.",
"fr": "Microsoft Copilot est votre compagnon pour informer, divertir et inspirer. Obtenez des conseils, des commentaires et des réponses simples."
},
"url": "copilot.microsoft.com",
"regExp": "^https?[:][/][/]([a-z0-9-]+[.])*copilot[.]microsoft[.]com[/]",
"version": "1.0.0",
"logo": "https://i.imgur.com/hw9Nbpb.png",
"thumbnail": "https://i.imgur.com/slgHdU8.png",
"color": "#E14F9D",
"category": "other",
"tags": [
"ai",
"language",
"human-like",
"conversations",
"multi-purpose"
],
"settings": [
{
"id": "lang",
"multiLanguage": true
},
{
"id": "showTitle",
"title": "Show chat title",
"icon": "fa-solid fa-message-quote",
"value": true,
"description": "Only work when sidebar open"
}
]
}
164 changes: 164 additions & 0 deletions websites/M/Microsoft Copilot/presence.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
const presence = new Presence({
clientId: '1450225438709387477',
})
const browsingTimestamp = Math.floor(Date.now() / 1000)

enum ActivityAssets {
Talking = 'https://i.imgur.com/aWWXjuc.png',
Logo = 'https://i.imgur.com/hw9Nbpb.png',
}

presence.on('UpdateData', async () => {
const { pathname } = document.location
const showTitle = await presence.getSetting<boolean>('showTitle')
const presenceData: PresenceData = {
largeImageKey: ActivityAssets.Logo,
startTimestamp: browsingTimestamp,
}

const strings = await presence.getStrings({
aiResponding: 'microsoftcopilot.aiResponding',
startNewConversation: 'microsoftcopilot.startNewConversation',
conversationStats: 'microsoftcopilot.conversationStats',
talkingWithAI: 'microsoftcopilot.talkingWithAI',
thinkingOfPrompt: 'microsoftcopilot.thinkingOfPrompt',
viewPublicImagesGenerated: 'microsoftcopilot.viewPublicImagesGenerated',
prompt: 'microsoftcopilot.prompt',
unknown: 'microsoftcopilot.unknown',
listeningDayNews: 'microsoftcopilot.listeningDayNews',
writingPage: 'microsoftcopilot.writingPage',
viewTheirLibrary: 'microsoftcopilot.viewTheirLibrary',
viewAGeneratedImage: 'microsoftcopilot.viewAGeneratedImage',
viewResearchReport: 'microsoftcopilot.viewResearchReport',
readingArticle: 'general.readingArticle',
checkingWeather: 'microsoftcopilot.checkingWeather',
watchingVideoArticle: 'microsoftcopilot.watchingVideoArticle',
discoverNews: 'microsoftcopilot.discoverNews',
discoverExperimentalFeatures: 'microsoftcopilot.discoverExperimentalFeatures',
generateAudioExpression: 'microsoftcopilot.generateAudioExpression',
viewPublic3DGenerations: 'microsoftcopilot.viewPublic3DGenerations',
viewTheir3DGenerations: 'microsoftcopilot.viewTheir3DGenerations',
playingWithAiGeneration: 'microsoftcopilot.playingWithAiGeneration',
})

const isTalking = document.querySelector(
'button[data-testid=stop-button]',
)

let wordCount = 0
for (const element of document.querySelectorAll(
'[data-content="user-message"],[data-content="ai-message"]',
)) {
const text = element.textContent
?.replace(/, |,\n|,|\. |\./g, ' ')
// eslint-disable-next-line regexp/no-dupe-disjunctions
.replace(/\d*|[/', ]/g, '')
if (text) {
wordCount += text.split(' ').slice(2, text.split(' ').length).length
}
}

if (pathname.split('/')[1] === 'chats') {
const sidebarButtonToggle = document.querySelector('div[data-testid="sidebar-container"] button[role="link"]')
const isSidebarOpen = sidebarButtonToggle?.parentElement?.className.includes('hidden') === false
if (showTitle && isSidebarOpen) {
presenceData.details = document.querySelector(
'div[role="listbox"] > div[role="option"][aria-selected="true"]',
)?.textContent
}
else {
presenceData.details = strings.talkingWithAI
}

presenceData.state = isTalking
? strings.aiResponding
: strings.conversationStats
.replace(
'{0}',
`${Number(
document.querySelectorAll('[data-content="user-message"]')
.length,
)}`,
)
.replace('{1}', `${wordCount}`)
presenceData.smallImageKey = isTalking ? ActivityAssets.Talking : null
}
else if (pathname.split('/')[1] === 'pages') {
const pageTitle = document.querySelector('h1[role="button"]')
const pageTitleInput = document.querySelector<HTMLInputElement>('input[type="text"]')
presenceData.details = strings.writingPage
presenceData.state = pageTitle?.textContent?.trim() || pageTitleInput?.value?.trim() || strings.unknown
}
else if (pathname.split('/')[1] === 'research') {
presenceData.details = strings.viewResearchReport
presenceData.state = document.querySelector('.text-base')?.nextElementSibling?.textContent?.trim() ?? strings.unknown
}
else if (pathname.split('/')[1] === 'discover') {
if (pathname.split('/')[2] === 'news-article') {
presenceData.details = strings.readingArticle
presenceData.state = document.querySelector('.content-title')?.textContent?.trim() ?? strings.unknown
}
else if (pathname.split('/')[2] === 'news-video') {
presenceData.details = strings.watchingVideoArticle
}
else if (pathname.split('/')[2] === 'news-gem') {
presenceData.details = strings.readingArticle
presenceData.state = document.querySelector('.gem-header-title')?.textContent?.trim() ?? strings.unknown
}
else if (pathname.split('/')[2] === 'weather') {
const data = document.querySelectorAll('div[data-testid="discover-weather-card"] span')
presenceData.details = strings.checkingWeather.replace('{0}', data[0]?.textContent ?? strings.unknown)
presenceData.state = `${data[1]?.textContent || ''} - ${data[2]?.textContent || ''} (${data[3]?.textContent || ''} / ${data[4]?.textContent || ''})`
}
else {
presenceData.details = strings.discoverNews
}
}
else if (pathname.split('/')[1] === 'imagine') {
presenceData.details = strings.viewPublicImagesGenerated
if (pathname.split('/')[2]) {
presenceData.state = strings.prompt.replace('{0}', document.querySelector('button.text-start')?.textContent?.trim() ?? strings.unknown)
}
}
else if (pathname.split('/')[1] === 'library') {
const imageOpened = document.querySelector('img[referrerpolicy="no-referrer"]')
presenceData.details = strings.viewTheirLibrary
if (imageOpened) {
presenceData.details = strings.viewAGeneratedImage
}
}
else if (pathname.split('/')[1] === 'labs') {
if (pathname.split('/')[4] === 'my-creations') {
presenceData.details = strings.viewTheir3DGenerations
}
else if (pathname.split('/')[3] === '3d-generations') {
presenceData.details = strings.viewPublic3DGenerations
}
else if (pathname.split('/')[2] === 'experiments') {
presenceData.details = strings.discoverExperimentalFeatures
presenceData.state = document.querySelector('main header')?.textContent?.trim() ?? strings.unknown
}
else if (pathname.split('/')[2] === 'audio-expression') {
presenceData.details = strings.generateAudioExpression
}
else {
presenceData.details = strings.discoverExperimentalFeatures
}
}
else if (pathname.split('/')[1] === 'daily') {
const chapters = document.querySelectorAll<HTMLDivElement>('[data-testid^="daily-briefing-chapter"]')
const activeChapter = Array.from(chapters).find(el => el.style.opacity === '1')
const newsTitle = activeChapter?.querySelector('h1[data-testid="chapter-title"]')
presenceData.details = strings.listeningDayNews
presenceData.state = newsTitle?.textContent?.trim() ?? strings.unknown
}
else if (pathname.split('/')[1] === 'gaming') {
presenceData.details = strings.playingWithAiGeneration
}
else {
presenceData.details = strings.startNewConversation
presenceData.state = strings.thinkingOfPrompt
}

presence.setActivity(presenceData)
})
Loading