Buen dia a todos! Creo que este artículo será interesante para todos los que usan Notion, pero por alguna razón no pudo pasar a él por completo.
Prehistoria
Estoy desarrollando
mi proyecto . En la página de destino después de ingresar el correo electrónico, se emite un enlace a una encuesta social basada en Formularios de Google. Las respuestas se registran en la placa de identificación en Google Drive.
El problema es que todo lo que
llevo conmigo lo guardo en Notion. Es cursi más conveniente. Manejado por copiar y pegar, aunque hubo pocas reseñas. Luego hubo más de ellos, y era necesario pensar en algo. ¿A quién le importa lo que pasó? Bienvenido a Cat.
El problema
Google Forms registra las respuestas solo en la placa de identificación, es decir, no hay otra receta aquí. Por lo tanto, tenía un plan: escuchemos a través de IFTTT las actualizaciones de las tabletas, enviemos nuevos datos al webhook, procesemos de alguna manera y cárguelos a Notion.
Para aquellos que no están familiarizados con IFTTT: este es un servicio que le permite realizar cadenas de acciones. Digamos, "la publicación vino en telegramas" - "la exportamos en VKontakte".
El plan comenzó a fallar: Notion no tiene una API oficial. Pero alguien lo revirtió e hizo
una API no oficial .
El plan final fue este:- Creamos el applet en IFTTT: “Se ha agregado una línea a la tableta; envíela al servidor
- Hacemos directamente el servidor que recibe los datos y los envía a Notion
El segundo problema apareció cuando resultó que IFTTT había roto la integración con Google Sheets y, por lo tanto, el applet no funcionaba.

Por lo tanto, tuve que cambiar el plan: bombeamos el csv'shku con Google Sheets, lo analizamos en el servidor y lanzamos todo lo nuevo en Notion. IFTTT se utiliza como desencadenante de todo el proceso.
Parte 1. CSV con Hojas de cálculo de Google
Esta parte es quizás la más fácil. Abrimos la mesa para ver (para que no tenga que molestarse con las cookies). A continuación, tome y copie el enlace para exportar CSV. Para hacer esto, simplemente presione Ctrl en el teclado y escriba Ctrl + Shift + J (es decir, abra la consola del desarrollador), vaya a la pestaña Red. Luego haga clic en Archivo - Descargar - CSV. Vemos la solicitud y copiamos el enlace.
Parte 2. Escribir un servidor
Como tenemos una biblioteca de Python, escribiremos en Django.
Ahora un poco sobre la estructura de mi mesa específicamente. Una tabla en Notion, a diferencia de una tabla en Hojas de cálculo de Google, tiene una columna "Referencia". Este es un enlace a otra tabla (en mi caso, una descripción de las funciones que les gustaron a los usuarios). El resto es generalmente claro: solo columnas con solo datos.
Vamos a Notion, ya estamos familiarizados con Ctrl + Shift + J, abre la consola, ve a Aplicación - Cookies, copia token_v2 y llámalo TOKEN. Luego vamos a la página que necesitamos con la placa y copiamos el enlace. Llamar NOCION. Si también tiene Relación, vaya a la página con Relación, copie el enlace y llame, por ejemplo, NOTION_FUNCTIONS
Luego, escriba el siguiente código (noción previa a la importación):
def index(request): if request.method == "POST": client = NotionClient(token_v2=TOKEN) database = client.get_collection_view(NOTION) current_rows = database.default_query().execute() database_functions = client.get_collection_view(NOTION_FUNCTIONS) current_rows_functions = database_functions.default_query().execute()
En él conectamos NotionClient, decimos „Bases de datos? Give two! "Y obtenemos los datos directamente de estas dos placas (por solicitud predeterminada, pero es posible con la clasificación, para más detalles, consulte la documentación de la biblioteca).
Luego debemos hacer lo siguiente: solicitar un CSV de Google y analizarlo. Lo haremos pandas'om.
result = requests.get(SHEET).content pandas_result = pd.read_csv(io.StringIO(result.decode('utf-8'))) timestamps = pandas_result[[" "]].values ages = pandas_result[[" "]].values sexes = pandas_result[[" "]].values cities = pandas_result[[" "]].values socials = pandas_result[[" ( )"]].values agreements = pandas_result[[" , - ."]].values control_usages = pandas_result[[" "]].values health_usages = pandas_result[[" "]].values prices = pandas_result[[" . :)"]].values mentions = pandas_result[[", , "]].values
Luego tenemos que revisar todos los datos de esta placa y verificar si se han agregado a Notion o no todavía. Para hacer esto, solicitamos datos de las placas.
def checkTimestamp(rows, timestamp): for i in range(0, len(rows)): row = rows[i] if row.name == timestamp: return True return False
Por separado, vale la pena mencionar acerca de "row.name", porque un lector atento probablemente preguntará: ¿qué es?
Este es el nombre de la columna en Notion (donde se almacenan los tiempos de grabación). De alguna manera no pude agregar con nombres rusos, así que cambié todos los nombres a inglés y los agregué.

Y ahora el código para verificar los datos y agregar una línea a la etiqueta Notion:
for i in range(0, len(timestamps)): if not checkTimestamp(current_rows, timestamps[i]): row = database.collection.add_row() health_usage = health_usages[i][0] control_usage = control_usages[i][0] ticks = health_usage + "," + control_usage row.title = timestamps[i][0] row.age = ages[i][0] row.sex = sexes[i][0] row.social_network = checkEmptiness(socials[i][0]) row.can_we_write_you = checkEmptiness(agreements[i][0]) row.city = checkEmptiness(cities[i][0]) row.controlling_examples = checkEmptiness(control_usages[i][0]) row.health_examples = checkEmptiness(health_usages[i][0]) row.cost = checkEmptiness(prices[i][0]) row.noticements = checkEmptiness(mentions[i][0]) row.castdev_relation = findIds(current_rows_functions, ticks)
checkEmptiness es una función que verifica si se le ha pasado un elemento nulo. Noción de alguna manera funcionó a regañadientes cuando le di cero campos, por lo que vale la pena escribir.
Ahora pasemos al análisis de las Relaciones, porque en la documentación oficial no lo vi. Para hacer un enlace a una línea desde otra base de datos, debe tomarlo (de esta línea) y transferirlo. En consecuencia, si se implica una matriz de enlaces a cadenas desde otra placa, debe tomar una matriz de sus identificadores. Personalmente agregué Relaciones por nombres de funciones.
def findIds(current_rows, titles): print("titles", titles) print("current rows", current_rows) array = [] for a in range(0, len(current_rows)): if current_rows[a].name in titles: array.append(current_rows[a].id) print("Ids", array) return array
Al final, después de crear las líneas, agregue la respuesta para que en el otro extremo sepan que la solicitud ha llegado.
return HttpResponse("Hello, habr.")
Taschemta con el servidor más importante está terminado, vaya a IFTTT.
Parte 3. IFTTT
Vaya a la
pestaña de creación de applet . Seleccionamos el disparador (en nuestro caso es Fecha y hora), establecemos "cada hora". Seleccionamos el Webhook activado (es decir, "ese"), especificamos nuestra dirección local (hasta ahora) para probarla. Bueno, eso es todo. Prueba.
Parte 4. Heroku
Pensaste con lo que estábamos jugando con este disparador del IFTTT: esto no es para pagar. Heroku ofrece una tarifa gratuita para alojar nuestras cosas. Lo principal es que el servicio duerme al menos 6 horas. Y definitivamente dormirá, porque lo llamamos a trabajar cada hora, y no cada minuto.

Además hacemos lo siguiente. Ve a heroku para
crear un nuevo proyecto . A continuación, instale
su cliente en su sistema operativo. Y luego hacemos todo de acuerdo con las instrucciones que aparecieron después de crear la aplicación.
Después de descargar todo en heroku, vaya a nuestro applet y edite la URL a una nueva.
Ahora la lista debe actualizarse cada hora. Hipotéticamente, IFTTT puede dar un error de que tiene algún tipo de solicitud larga, pero esto no es tan importante.
Actualización
Resultó ser importante. Cuando el IFTTT detecta errores persistentes, comienza a omitir los applets.
Para resolver este problema, simplemente inicie un nuevo hilo para todo esto, dando la respuesta de inmediato.
if request.method == "POST": thread = Thread(target=run_notion_import) thread.start() return HttpResponse("Hello, habr.")
Otra idea que olvidé expresar en el artículo es verificar la nulidad utilizando el método estándar de pandas.
Es decir, su cheque se verá así:
if not pd.isna(health_usages[i][0]): row.health_examples = health_usages[i][0]