From 71a2bec0999ff7750fe214a322b8991299044193 Mon Sep 17 00:00:00 2001
From: root <o.o@bitheaven.ru>
Date: Sun, 30 Mar 2025 13:50:23 +0500
Subject: [PATCH] Add basic functions

---
 css/style.css |   4 ++
 index.html    |  21 ++++++++-
 js/index.js   | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 140 insertions(+), 1 deletion(-)

diff --git a/css/style.css b/css/style.css
index 666e43a..612b861 100644
--- a/css/style.css
+++ b/css/style.css
@@ -8,3 +8,7 @@ body {
 	margin: auto; 
 	max-width: 768px;
 }
+
+table {
+	
+}
diff --git a/index.html b/index.html
index e0bbd6a..7fbd406 100644
--- a/index.html
+++ b/index.html
@@ -4,8 +4,27 @@
 	<meta charset="UTF-8">
 	<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0">
 	<link rel="stylesheet" href="/css/style.css?v=1">
-	<script src="/js/index.js?v=1" defer>
+	<script src="/js/index.js?v=1" defer></script>
 </head>
 <body>
+	id, название сделки, бюджет, название контакта номер телефона.
+	<table>
+		<tr>
+			<th>ID</th>
+			<th>Название</th>
+			<th>Бюджет</th>
+			<th>Контакт</th>
+			<th>Телефон</th>
+		</tr>
+		<div id="table-content">
+			<tr>
+				<td>1111</td>
+				<td>Название</td>
+				<td>Бюджет</td>
+				<td>Контакт</td>
+				<td>Телефон</td>
+			</tr>
+		</div>
+	</table>
 </body>
 </html>
diff --git a/js/index.js b/js/index.js
index e69de29..69d8a3b 100644
--- a/js/index.js
+++ b/js/index.js
@@ -0,0 +1,116 @@
+const DOMAIN = 'bitheaven.amocrm.ru'
+const CLIENT_ID = '8c5dbb32-197d-44ff-87dd-c52fb8ca51d6'
+const CLIENT_SECRET = '2DsrI50jwoEMmTXmFCGDGebQ8ULo7PzKHsYNbKZfBGmy8MBEIOiby2HITqssXYIV'
+const REDIRECT_URI = 'https://amocrm-web.sectorlambda.ru/'
+
+const ACCESS_TOKEN = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IjgwMDMyMjQ1Mzg5MjM2MGJlMTFjZjk5ZDkyNDZjMzYzYWUzNGM5OTliNDIyYTc5MWMwMmE1MTEyMTM4MjJlMWMyZWFmNGU2OWY4MGFkODM0In0.eyJhdWQiOiI4YzVkYmIzMi0xOTdkLTQ0ZmYtODdkZC1jNTJmYjhjYTUxZDYiLCJqdGkiOiI4MDAzMjI0NTM4OTIzNjBiZTExY2Y5OWQ5MjQ2YzM2M2FlMzRjOTk5YjQyMmE3OTFjMDJhNTExMjEzODIyZTFjMmVhZjRlNjlmODBhZDgzNCIsImlhdCI6MTc0MzI4MjcxOCwibmJmIjoxNzQzMjgyNzE4LCJleHAiOjE3NDMzNjkxMTgsInN1YiI6IjExOTQ5NDAyIiwiZ3JhbnRfdHlwZSI6IiIsImFjY291bnRfaWQiOjMyMzIyMTI2LCJiYXNlX2RvbWFpbiI6ImFtb2NybS5ydSIsInZlcnNpb24iOjIsInNjb3BlcyI6WyJwdXNoX25vdGlmaWNhdGlvbnMiLCJmaWxlcyIsImNybSIsImZpbGVzX2RlbGV0ZSIsIm5vdGlmaWNhdGlvbnMiXSwiaGFzaF91dWlkIjoiZDFjYzg0ODQtNzA1OC00NGQ2LWI5Y2MtMWIyZGE1YjFiMjJlIiwiYXBpX2RvbWFpbiI6ImFwaS1iLmFtb2NybS5ydSJ9.MyK_jsN611TWRZp5oQhqpJPmNs-5Iye5-X5bKycDvtfp1LFXA8lK9jjgK3nQm1yrdqpwGIPUcOqzXEDxSjwfKwwtbHAsLgJMcd6XF1UKADiNXpO1aFw9SJ1K9bGMDvO1qqiLFxqMpNe_VaYnXSdQKPSjNIg0qGIizvwifWo5EfoshoOIWBu0LBT0GulhVN42XcADwwkZnQhCOnO4gp2Sms3bc4Wf8u6BOW_EB5ZESVzf2Q1DetcxXz8Oo6NTAD8tJiEHEGpLJfFNI_2fUC_elCpr3i_Qn9XbnNfnFOi6APkTCtGOFUBUjOmJZz0RHlj9elPfK2_mJRGnAVb1TEumWg'
+const REFRESH_TOKEN = 'def5020054ff9f61f3a1d4908fad5fbb447c3411e943cd5b658707882fdf7e00652719cf68e195e864e025cd01eff1dc10610ccd53f0f9c8738288ac3712b15f7378af17746e7d2c4830cacf2dfb887349d009a63a8759238038fc9b10bdc9445584405798adb06c83cd2190d1be9b6d18da92bbbcdc45bf9a0b5d537879ed2dc7b17e001a49d8645be88ed1733425824489645fbe64c36f954cfacb83388181a113c3db9d960c0e3aa9553aa9fb948c575302606f0908fe937242ce683787b68435243950eb957110b94119c1b10cb73850ee2c8bf7b1f4af4038708e73adf4713dd2ab138fa091e52f18e17cc43ba9a58ef60748ff7fd1c6cbe2b91a4123cc54807685b93739c70622c34e4bf212c656d8bfdef22597845daafef73d503d0e63f93a5297f01d22226aa5a841a179730c44f25193efb03bec6e17aebeea55ed12745ab5739cd18db21d6e128f25a24c69bd4a751d2c303455e46ed3767e9dadb157c09ae9360c15a93da16e7f59b1f54c22fb96cf69e64e73f8c94c1cba41906186021d3304dd1032e1d63df32e818e2518243484457e5f142ca13068d2841e14b6ce6f6e9d4a7c538c0d0432c276e605418e7f46b6b3d43b96acebd99d0ab5da10f35f534a61b1476b80aadf113b0e2cd28ae2072c47f6c85dec1ac3c5681186f08f46320aac28de3e93f0aea4'
+
+const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
+
+const getTokens = async authCode => {
+	try {
+		const response = await fetch(`https://${DOMAIN}/oauth2/access_token`, {
+			method: 'POST',
+			headers: {
+				'Content-Type': 'application/json'
+			},
+			body: JSON.stringify({
+				client_id: CLIENT_ID,
+				client_secret: CLIENT_SECRET,
+				grant_type: 'authorization_code',
+				code: authCode,
+				redirect_uri: REDIRECT_URI
+			})
+		})
+
+		if (!response.ok) {
+			throw new Error(`Ошибка: ${response.status}`)
+		}
+
+		const data = await response.json()
+		return {
+			access_token: data.access_token,
+			refresh_token: data.refresh_token
+		}
+	} catch (error) {
+		console.error('Ошибка при получении токенов:', error)
+		throw error
+	}
+}
+
+const getContact = async id => {
+	try {
+		const response = await fetch(`https://${DOMAIN}/api/v4/contacts/${id}`, {
+			method: 'GET',
+			headers: {
+				'Authorization': `Bearer ${ACCESS_TOKEN}`,
+				'Content-Type': 'application/json'
+			}
+		})
+
+		if (!response.ok) {
+			throw new Error(`Ошибка: ${response.status}`)
+		}
+
+		const data = await response.json()
+
+		return data
+	} catch (error) {
+		console.error('Ошибка при получении токенов:', error)
+		throw error
+	}
+}
+
+const getLeads = async (page = 1, limit = 2) => {
+	try {
+		const response = await fetch(`https://${DOMAIN}/api/v4/leads?page=${page}&limit=${limit}&with=contacts`, {
+			method: 'GET',
+			headers: {
+				'Authorization': `Bearer ${ACCESS_TOKEN}`,
+				'Content-Type': 'application/json'
+			}
+		})
+
+		if (!response.ok) {
+			throw new Error(`Ошибка: ${response.status}`)
+		}
+
+		const data = await response.json()
+
+		const leads = []
+		data._embedded.leads.forEach(async lead => {
+				const contact =
+					lead._embedded.contacts.length
+					? await getContact(lead._embedded.contacts[0].id)
+					: null
+
+			leads.push({
+				lead: lead,
+				contact: contact
+			})
+		})
+
+		return leads
+	} catch (error) {
+		console.error('Ошибка при получении токенов:', error)
+		throw error
+	}
+}
+
+const getAllLeads = async () => {
+	let page = 1
+	while (true) {
+		try {
+			const leads = await getLeads(page++)
+		} catch (error) {
+			break
+		}
+		await sleep(1000)
+	}
+}
+
+
+(async () => {
+
+})()