Lorem ipsum content with an image and a random file below
import process from "node:process";
import { TodoistApi } from "npm:@doist/todoist-api-typescript";
import { Client } from "npm:@notionhq/client";
const TODOIST_API_KEY = process.env.TODOIST_API_KEY;
const todoistapi = new TodoistApi(TODOIST_API_KEY);
const NOTION_API_KEY = process.env.NOTION_API_KEY;
const notion = new Client({
auth: NOTION_API_KEY,
});
var add_to_notion_todoist_project_id = "PROJECT_ID_HERE";
var todoist_dict_mapping = {
"habit": {
"todoist-section-id": "SECTION_ID_HERE",
"notion-map-type": "page",
"notion-id": "PAGE_ID_HERE",
},
"papers": {
"todoist-section-id": "SECTION_ID_HERE",
"notion-map-type": "database",
"notion-id": "DB_ID_HERE",
},
};
function getNotionId(section_id) {
if (!section_id) {
return [todoist_dict_mapping["dump"]["notion-map-type"], todoist_dict_mapping["dump"]["notion-id"]];
}
for (var key in todoist_dict_mapping) {
if (todoist_dict_mapping[key]["todoist-section-id"] === section_id) {
return [
todoist_dict_mapping[key]["notion-map-type"] || todoist_dict_mapping["dump"]["notion-map-type"],
todoist_dict_mapping[key]["notion-id"] || todoist_dict_mapping["dump"]["notion-id"],
];
}
}
return [todoist_dict_mapping["dump"]["notion-map-type"], todoist_dict_mapping["dump"]["notion-id"]];
}
function convertDateObject(due) {
function convertToISOWithOffset(datetimeStr, timezoneStr) {
const date = new Date(datetimeStr);
const [, sign, hours, minutes] = timezoneStr.match(/GMT ([+-])(\d{1,2}):(\d{2})/);
date.setUTCMinutes(date.getUTCMinutes() + (parseInt(hours) * 60 + parseInt(minutes)) * (sign === "+" ? 1 : -1));
return date.toISOString().split(".")[0]
+ `${sign}${String(hours).padStart(2, "0")}:${String(minutes).padStart(2, "0")}`;
}
const formatDate = (date, datetime, timezone) => {
let isoString = datetime ? datetime : date;
if (timezone && timezone.startsWith("GMT") && timezone.length > 3) {
return convertToISOWithOffset(datetime, timezone);
} else {
return isoString;
}
};
return {
start: due ? formatDate(due.date, due.datetime, due.timezone) : new Date().toISOString(),
end: null,
time_zone: due && due.datetime && due.timezone && due.timezone.startsWith("GMT") && due.timezone.length > 3
? null
: (due && due.datetime && due.timezone ? due.timezone : "America/Los_Angeles"),
};
}
async function addCalloutToNotionPage(page_id, content, date) {
console.log(JSON.stringify(date));
const response = await notion.blocks.children.append({
block_id: page_id,
children: [{
"callout": {
"rich_text": [{
"type": "mention",
"mention": {
"type": "date",
"date": date,
},
}],
"icon": {
"type": "external",
"external": {
"url": "https://www.notion.so/icons/circle-dot_lightgray.svg",
},
},
"children": [{
"paragraph": {
"rich_text": [{
"text": {
"content": content,
},
}],
},
}],
},
}],
});
console.log(JSON.stringify(response));
}
async function addPageToNotionDatabse(database_id, content) {
const response = await notion.pages.create({
"parent": {
"type": "database_id",
"database_id": database_id,
},
"properties": {
"Name": {
"title": [{
"text": {
"content": content,
},
}],
},
},
});
}
export default async function(interval: Interval) {
var tasks = await todoistapi.getTasks({
projectId: add_to_notion_todoist_project_id,
});
for (const task of tasks) {
console.log(task);
const [mappedNotionType, mappedNotionId] = getNotionId(task.sectionId);
if (mappedNotionId)
{
if (mappedNotionType == "page" && mappedNotionId) {
addCalloutToNotionPage(mappedNotionId, task.content, convertDateObject(task.due));
}
else if (mappedNotionType == "database" && mappedNotionId) {
addPageToNotionDatabse(mappedNotionId, task.content);
}
todoistapi.deleteTask(task.id);
}
}
}
Code in case you want to host somewhere else
import process from "node:process";
import { TodoistApi } from "npm:@doist/todoist-api-typescript";
import { Client } from "npm:@notionhq/client";
const TODOIST_API_KEY = process.env.TODOIST_API_KEY;
const todoistapi = new TodoistApi(TODOIST_API_KEY);
const NOTION_API_KEY = process.env.NOTION_API_KEY;
const notion = new Client({
auth: NOTION_API_KEY,
});
var add_to_notion_todoist_project_id = "PROJECT_ID_HERE";
var todoist_dict_mapping = {
"habit": {
"todoist-section-id": "SECTION_ID_HERE",
"notion-map-type": "page",
"notion-id": "PAGE_ID_HERE",
},
"papers": {
"todoist-section-id": "SECTION_ID_HERE",
"notion-map-type": "database",
"notion-id": "DB_ID_HERE",
},
};
function getNotionId(section_id) {
if (!section_id) {
return [todoist_dict_mapping["dump"]["notion-map-type"], todoist_dict_mapping["dump"]["notion-id"]];
}
for (var key in todoist_dict_mapping) {
if (todoist_dict_mapping[key]["todoist-section-id"] === section_id) {
return [
todoist_dict_mapping[key]["notion-map-type"] || todoist_dict_mapping["dump"]["notion-map-type"],
todoist_dict_mapping[key]["notion-id"] || todoist_dict_mapping["dump"]["notion-id"],
];
}
}
return [todoist_dict_mapping["dump"]["notion-map-type"], todoist_dict_mapping["dump"]["notion-id"]];
}
function convertDateObject(due) {
function convertToISOWithOffset(datetimeStr, timezoneStr) {
const date = new Date(datetimeStr);
const [, sign, hours, minutes] = timezoneStr.match(/GMT ([+-])(\d{1,2}):(\d{2})/);
date.setUTCMinutes(date.getUTCMinutes() + (parseInt(hours) * 60 + parseInt(minutes)) * (sign === "+" ? 1 : -1));
return date.toISOString().split(".")[0]
+ `${sign}${String(hours).padStart(2, "0")}:${String(minutes).padStart(2, "0")}`;
}
const formatDate = (date, datetime, timezone) => {
let isoString = datetime ? datetime : date;
if (timezone && timezone.startsWith("GMT") && timezone.length > 3) {
return convertToISOWithOffset(datetime, timezone);
} else {
return isoString;
}
};
return {
start: due ? formatDate(due.date, due.datetime, due.timezone) : new Date().toISOString(),
end: null,
time_zone: due && due.datetime && due.timezone && due.timezone.startsWith("GMT") && due.timezone.length > 3
? null
: (due && due.datetime && due.timezone ? due.timezone : "America/Los_Angeles"),
};
}
async function addCalloutToNotionPage(page_id, content, date) {
console.log(JSON.stringify(date));
const response = await notion.blocks.children.append({
block_id: page_id,
children: [{
"callout": {
"rich_text": [{
"type": "mention",
"mention": {
"type": "date",
"date": date,
},
}],
"icon": {
"type": "external",
"external": {
"url": "https://www.notion.so/icons/circle-dot_lightgray.svg",
},
},
"children": [{
"paragraph": {
"rich_text": [{
"text": {
"content": content,
},
}],
},
}],
},
}],
});
console.log(JSON.stringify(response));
}
async function addPageToNotionDatabse(database_id, content) {
const response = await notion.pages.create({
"parent": {
"type": "database_id",
"database_id": database_id,
},
"properties": {
"Name": {
"title": [{
"text": {
"content": content,
},
}],
},
},
});
}
export default async function(interval: Interval) {
var tasks = await todoistapi.getTasks({
projectId: add_to_notion_todoist_project_id,
});
for (const task of tasks) {
console.log(task);
const [mappedNotionType, mappedNotionId] = getNotionId(task.sectionId);
if (mappedNotionId)
{
if (mappedNotionType == "page" && mappedNotionId) {
addCalloutToNotionPage(mappedNotionId, task.content, convertDateObject(task.due));
}
else if (mappedNotionType == "database" && mappedNotionId) {
addPageToNotionDatabse(mappedNotionId, task.content);
}
todoistapi.deleteTask(task.id);
}
}
}
sample2.html
Download