-
Notifications
You must be signed in to change notification settings - Fork 512
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into update-formula-aarch64-apple-darwin-0e24c5ca…
…a49839487e3c18fcd69931d1a61feccb
- Loading branch information
Showing
5 changed files
with
292 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
87 changes: 87 additions & 0 deletions
87
examples/typescript/pipe-sync-meetings-to-notion/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
|
||
|
||
in screenpipe we have a plugin system called "pipe store" or "pipes" | ||
|
||
think of it like this: | ||
|
||
screenpipe data -> your pipe like "AI annotate" or "send to salesforce" | ||
|
||
a more dev-friendly explanation: | ||
|
||
screenpipe | AI tag | notion update | ||
|
||
or | ||
|
||
screenpipe | AI tag | slack send report | ||
|
||
or | ||
|
||
screenpipe | fill salesforce | ||
|
||
or | ||
|
||
screenpipe | logs daily | ||
|
||
basically it would read, process, annotate, analyse, summarize, send, your data customisable to your desire, effortlessly | ||
|
||
### pipe-sync-meetings-to-notion | ||
|
||
this is an experimental, but official pipe, that will sync your meetings to notion | ||
|
||
this is how you run it through the app: | ||
|
||
|
||
## Setup | ||
|
||
1. create a notion integration: | ||
- go to https://www.notion.so/my-integrations | ||
- click "new integration" | ||
- give it a name (e.g., "screenpipe meeting sync") | ||
- select the workspace where you want to sync your meetings | ||
- click "submit" to create the integration | ||
|
||
2. get your notion api key: | ||
- in the integration page, find the "internal integration token" | ||
- copy this token, you'll need it later | ||
|
||
3. create a database in notion: | ||
- create a new page in notion | ||
- add a database to this page | ||
- add columns: title, date, transcription + optionally notion ai columns if you want | ||
- share this page with your integration (click three dots, connections, your integration) | ||
|
||
4. get your notion database id: | ||
- open your database in notion | ||
- look at the url, it should look like: https://www.notion.so/yourworkspace/83c75a51b3bd4a) | ||
- the part after the last slash and before the ? is your database id | ||
|
||
now, your meeting transcriptions will automatically sync to your notion database! | ||
|
||
|
||
if you're in dev mode you can run the cli like this: | ||
|
||
```bash | ||
export SCREENPIPE_NOTION_API_KEY=secret_abcd | ||
export SCREENPIPE_NOTION_DATABASE_ID=1234567890 | ||
screenpipe --pipe ./examples/typescript/pipe-sync-meetings-to-notion/main.js | ||
``` | ||
|
||
please look at the code, it's 99% normal JS but there are limitations currently: | ||
- you cannot use dependencies (yet) | ||
- untested with typescript (but will make pipes TS first soon) | ||
|
||
i recommend you copy paste the current main.js file into AI and ask some changes for whatever you want to do, make sure to run an infinite loop also | ||
|
||
get featured in the pipe store: | ||
|
||
<img width="1312" alt="Screenshot 2024-08-27 at 17 06 45" src="https://github.com/user-attachments/assets/b6856bf4-2cfd-4888-be11-ee7baae6b84b"> | ||
|
||
just ask @louis030195 | ||
|
||
### what's next for pipes | ||
|
||
- use dependencies (like vercel/ai so cool) | ||
- TS | ||
- access to screenpipe desktop api (e.g. trigger notifications, customise what cursor-like @ are in the chat, etc.) | ||
- easier to publish your pipes (like obsidian store) | ||
- everything frictionless, effortless, and maximize the value you get out of screenpipe |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
const INTERVAL = 30 * 1000; // 30 seconds in milliseconds | ||
const NOTION_API_URL = 'https://api.notion.com/v1/pages'; | ||
const NOTION_DATABASE_ID = process.env.SCREENPIPE_NOTION_DATABASE_ID; | ||
const NOTION_API_KEY = process.env.SCREENPIPE_NOTION_API_KEY; | ||
|
||
|
||
|
||
async function queryScreenpipe(startTime, endTime) { | ||
try { | ||
const queryParams = `start_time=${startTime}&end_time=${endTime}&limit=50&content_type=audio`; | ||
const response = await fetch(`http://localhost:3030/search?${queryParams}`); | ||
if (!response.ok) { | ||
throw new Error(`HTTP error! status: ${response.status}`); | ||
} | ||
return await response.json(); | ||
} catch (error) { | ||
console.error("Error querying screenpipe:", error.toString()); | ||
return []; | ||
} | ||
} | ||
|
||
async function syncAudioToNotion(audioData) { | ||
try { | ||
const title = `Audio - ${audioData.content.timestamp}`; | ||
const date = audioData.content.timestamp; | ||
const transcription = audioData.content.transcription; | ||
|
||
// Split transcription into chunks of 2000 characters | ||
const chunks = splitTranscription(transcription); | ||
|
||
for (let i = 0; i < chunks.length; i++) { | ||
const response = await fetch(NOTION_API_URL, { | ||
method: 'POST', | ||
headers: { | ||
'Authorization': `Bearer ${NOTION_API_KEY}`, | ||
'Notion-Version': '2022-06-28', | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify({ | ||
parent: { database_id: NOTION_DATABASE_ID }, | ||
properties: { | ||
Title: { title: [{ text: { content: `${title} (Part ${i + 1}/${chunks.length})` } }] }, | ||
Date: { date: { start: date } }, | ||
Transcription: { rich_text: [{ text: { content: chunks[i] } }] }, | ||
}, | ||
}), | ||
}); | ||
|
||
if (!response.ok) { | ||
const errorBody = await response.text(); | ||
throw new Error(`HTTP error! status: ${response.status}, body: ${errorBody}`); | ||
} | ||
} | ||
|
||
console.log("Audio synced to Notion successfully"); | ||
} catch (error) { | ||
console.error("Error syncing audio to Notion:", error); | ||
} | ||
} | ||
|
||
function splitTranscription(transcription, chunkSize = 2000) { | ||
const chunks = []; | ||
for (let i = 0; i < transcription.length; i += chunkSize) { | ||
chunks.push(transcription.slice(i, i + chunkSize)); | ||
} | ||
return chunks; | ||
} | ||
|
||
async function streamAudioToNotion() { | ||
console.log("Starting Audio Stream to Notion"); | ||
|
||
while (true) { | ||
try { | ||
const now = new Date(); | ||
const thirtySecondsAgo = new Date(now.getTime() - INTERVAL); | ||
|
||
const audioData = await queryScreenpipe(thirtySecondsAgo.toISOString(), now.toISOString()); | ||
|
||
console.log("Audio data:", audioData); | ||
for (const audio of audioData.data) { | ||
await syncAudioToNotion(audio); | ||
} | ||
} catch (error) { | ||
console.error("Error syncing audio to Notion:", { | ||
message: error.message, | ||
stack: error.stack, | ||
audioData: JSON.stringify(audioData) | ||
}); | ||
} | ||
await new Promise((resolve) => setTimeout(resolve, INTERVAL)); | ||
} | ||
} | ||
|
||
streamAudioToNotion(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters