├── .env.example ├── .gitignore ├── README.md ├── index.js ├── package-lock.json └── package.json /.env.example: -------------------------------------------------------------------------------- 1 | YOUTUBE_KEY_API='' 2 | 3 | PGHOST = '' 4 | PGUSER = '' 5 | PGPASSWORD = '' 6 | PGDATABASE = '' 7 | PGPORT=5432 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | /node_modules -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | "# Subscriptor-Data-Parser" 2 | 3 | La idea de esto, es ayudar a que las comunidades sean mas fuertes y se puedan conocer mejor entre si. 4 | 5 | Usarlo de forma etica y por el bien comun. -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config() 2 | const { Client } = require('pg') 3 | 4 | const client = new Client({ 5 | ssl: { 6 | rejectUnauthorized: false 7 | } 8 | }); 9 | 10 | const videoId = "PaRam-aY9p0"; 11 | 12 | const youtubeClient = require("youtube-fast-api") 13 | 14 | const ytClient = new youtubeClient(process.env.YOUTUBE_KEY_API); 15 | 16 | const videoComments = ytClient.getAllComments(videoId); 17 | 18 | videoComments.then(videoData => { 19 | saveVideoData(videoData); 20 | }) 21 | 22 | function getUserData(videoData) { 23 | return { 24 | "authorDisplayName": videoData.authorDisplayName, 25 | "authorProfileImageUrl": videoData.authorProfileImageUrl, 26 | "authorChannelUrl": videoData.authorChannelUrl, 27 | "authorChannelId": videoData.authorChannelId 28 | } 29 | } 30 | 31 | function getCommentsData(videoData) { 32 | return { 33 | "videoId": videoData.videoId, 34 | "textDisplay": videoData.textDisplay, 35 | "textOriginal": videoData.textOriginal, 36 | "canRate": videoData.canRate, 37 | "viewerRating": videoData.viewerRating, 38 | "likeCount": videoData.likeCount, 39 | "publishedAt": videoData.publishedAt, 40 | "updatedAt": videoData.updatedAt, 41 | "id": videoData.id, 42 | "commentby": videoData.authorChannelId 43 | }; 44 | } 45 | 46 | //Guarda la informacion del video en la base de datos 47 | function saveVideoData(videoData) { 48 | const usersData = videoData.map(data => getUserData(data)); 49 | saveUserInDataBase(usersData) 50 | const commentsData = videoData.map(data => getCommentsData(data)); 51 | saveCommentsInDataBase(commentsData); 52 | } 53 | 54 | function saveUserInDataBase(usersData) { 55 | 56 | client.connect() 57 | Promise.all(usersData.map(user => saveUserInDataBase(user))).finally(x => client.end()); 58 | 59 | } 60 | 61 | function saveCommentsInDataBase(commentsData) { 62 | 63 | client.connect() 64 | Promise.all(commentsData.map(comment => saveCommentDataBase(comment))).finally(x => client.end()); 65 | 66 | } 67 | 68 | 69 | function saveUserInDataBase(user) { 70 | const insertQuery = `INSERT INTO usuarios (authordisplayname, authorprofileimageurl, authorchannelurl, authorchannelid) VALUES($1,$2,$3,$4);`; 71 | 72 | const values = [user.authorDisplayName, user.authorProfileImageUrl, user.authorChannelUrl, user.authorChannelId] 73 | 74 | return client 75 | .query(insertQuery, values) 76 | .then(res => { 77 | console.log("Todo ok") 78 | 79 | }) 80 | .catch(e => console.error(e.stack)) 81 | 82 | } 83 | 84 | function saveCommentDataBase(comment) { 85 | 86 | const insertQuery = `INSERT INTO public.comentarios (videoid, textdisplay, textoriginal, canrate, viewerrating, likecount, publishedat, updatedat, id, commentby) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);`; 87 | 88 | const values = [comment.videoId, 89 | comment.textDisplay, 90 | comment.textOriginal, 91 | comment.canRate, 92 | comment.viewerRating, 93 | comment.likeCount, 94 | comment.publishedAt, 95 | comment.updatedAt, 96 | comment.id, 97 | comment.authorChannelId] 98 | 99 | return client 100 | .query(insertQuery, values) 101 | .then(res => { 102 | console.log("Todo ok") 103 | 104 | }) 105 | .catch(e => console.error(e.stack)) 106 | 107 | 108 | /* 109 | INSERT INTO public.comentarios 110 | (videoid, textdisplay, textoriginal, canrate, viewerrating, likecount, publishedat, updatedat, id, commentby) 111 | VALUES('', '', '', '', '', '', '', '', '', ''); */ 112 | 113 | } 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Youtube-Channel-Save-Data", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "buffer-writer": { 8 | "version": "2.0.0", 9 | "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", 10 | "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" 11 | }, 12 | "dotenv": { 13 | "version": "10.0.0", 14 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", 15 | "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==" 16 | }, 17 | "inherits": { 18 | "version": "2.0.4", 19 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 20 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 21 | }, 22 | "packet-reader": { 23 | "version": "1.0.0", 24 | "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", 25 | "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" 26 | }, 27 | "pg": { 28 | "version": "8.7.1", 29 | "resolved": "https://registry.npmjs.org/pg/-/pg-8.7.1.tgz", 30 | "integrity": "sha512-7bdYcv7V6U3KAtWjpQJJBww0UEsWuh4yQ/EjNf2HeO/NnvKjpvhEIe/A/TleP6wtmSKnUnghs5A9jUoK6iDdkA==", 31 | "requires": { 32 | "buffer-writer": "2.0.0", 33 | "packet-reader": "1.0.0", 34 | "pg-connection-string": "^2.5.0", 35 | "pg-pool": "^3.4.1", 36 | "pg-protocol": "^1.5.0", 37 | "pg-types": "^2.1.0", 38 | "pgpass": "1.x" 39 | } 40 | }, 41 | "pg-connection-string": { 42 | "version": "2.5.0", 43 | "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", 44 | "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==" 45 | }, 46 | "pg-int8": { 47 | "version": "1.0.1", 48 | "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", 49 | "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" 50 | }, 51 | "pg-pool": { 52 | "version": "3.4.1", 53 | "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.4.1.tgz", 54 | "integrity": "sha512-TVHxR/gf3MeJRvchgNHxsYsTCHQ+4wm3VIHSS19z8NC0+gioEhq1okDY1sm/TYbfoP6JLFx01s0ShvZ3puP/iQ==" 55 | }, 56 | "pg-protocol": { 57 | "version": "1.5.0", 58 | "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz", 59 | "integrity": "sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ==" 60 | }, 61 | "pg-types": { 62 | "version": "2.2.0", 63 | "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", 64 | "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", 65 | "requires": { 66 | "pg-int8": "1.0.1", 67 | "postgres-array": "~2.0.0", 68 | "postgres-bytea": "~1.0.0", 69 | "postgres-date": "~1.0.4", 70 | "postgres-interval": "^1.1.0" 71 | } 72 | }, 73 | "pgpass": { 74 | "version": "1.0.4", 75 | "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.4.tgz", 76 | "integrity": "sha512-YmuA56alyBq7M59vxVBfPJrGSozru8QAdoNlWuW3cz8l+UX3cWge0vTvjKhsSHSJpo3Bom8/Mm6hf0TR5GY0+w==", 77 | "requires": { 78 | "split2": "^3.1.1" 79 | } 80 | }, 81 | "postgres-array": { 82 | "version": "2.0.0", 83 | "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", 84 | "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" 85 | }, 86 | "postgres-bytea": { 87 | "version": "1.0.0", 88 | "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", 89 | "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=" 90 | }, 91 | "postgres-date": { 92 | "version": "1.0.7", 93 | "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", 94 | "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==" 95 | }, 96 | "postgres-interval": { 97 | "version": "1.2.0", 98 | "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", 99 | "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", 100 | "requires": { 101 | "xtend": "^4.0.0" 102 | } 103 | }, 104 | "readable-stream": { 105 | "version": "3.6.0", 106 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 107 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 108 | "requires": { 109 | "inherits": "^2.0.3", 110 | "string_decoder": "^1.1.1", 111 | "util-deprecate": "^1.0.1" 112 | } 113 | }, 114 | "safe-buffer": { 115 | "version": "5.2.1", 116 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 117 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 118 | }, 119 | "split2": { 120 | "version": "3.2.2", 121 | "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", 122 | "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", 123 | "requires": { 124 | "readable-stream": "^3.0.0" 125 | } 126 | }, 127 | "string_decoder": { 128 | "version": "1.3.0", 129 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 130 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 131 | "requires": { 132 | "safe-buffer": "~5.2.0" 133 | } 134 | }, 135 | "util-deprecate": { 136 | "version": "1.0.2", 137 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 138 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 139 | }, 140 | "xtend": { 141 | "version": "4.0.2", 142 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", 143 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" 144 | }, 145 | "youtube-fast-api": { 146 | "version": "1.0.6", 147 | "resolved": "https://registry.npmjs.org/youtube-fast-api/-/youtube-fast-api-1.0.6.tgz", 148 | "integrity": "sha512-7Q3UJOde/CmsBMMVjDiQ4BiDf2X/C5me/E5kpv9Vh+EUgW93NET18S3DLKPfL2UTPDQcHya+pmzsumH7Hb0iCw==" 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Youtube-Channel-Save-Data", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "Damian Sire ", 11 | "license": "ISC", 12 | "dependencies": { 13 | "dotenv": "^10.0.0", 14 | "pg": "^8.7.1", 15 | "youtube-fast-api": "^1.0.6" 16 | } 17 | } 18 | --------------------------------------------------------------------------------