2022-08-04 23:07:59 +02:00
import Masto from "mastodon" ;
2022-08-08 15:25:09 +02:00
import dotenv from "dotenv" ;
2022-12-07 23:15:07 +01:00
import sharp from 'sharp' ;
import fs from 'fs' ;
import https from 'https' ;
2023-03-10 11:20:37 +01:00
import moment from "moment" ;
2022-08-08 16:17:04 +02:00
2023-03-10 11:20:37 +01:00
import Parser from 'rss-parser' ;
2022-08-08 16:17:04 +02:00
2023-03-04 22:53:12 +01:00
2022-12-07 23:15:07 +01:00
let local _node _env _conf = dotenv . config ( )
2022-12-14 17:31:03 +01:00
const myArgs = process . argv . slice ( 2 ) ;
2023-03-03 15:19:09 +01:00
export const reallySendPost = hasCliArgument ( '--force' ) ;
export const folderBlogPostsPreview = process . cwd ( ) + '/assets/blog_posts_medias/'
2022-08-04 23:07:59 +02:00
2023-03-10 11:20:37 +01:00
2022-08-04 23:07:59 +02:00
export function randomIntFromInterval ( min , max ) { // min and max included
2022-11-22 10:55:11 +01:00
return Math . floor ( Math . random ( ) * ( max - min + 1 ) + min ) | 1
2022-08-04 23:07:59 +02:00
}
2022-08-08 16:17:04 +02:00
2022-08-04 23:07:59 +02:00
export function getRandomElementOfArray ( listItems ) {
return listItems [ Math . floor ( Math . random ( ) * listItems . length ) ]
2022-08-05 14:57:53 +02:00
}
let nowDate = new Date ( )
export let defaultConfigMasto = {
author : 'curator' ,
visibility : 'public' ,
language : 'fr' ,
sensitive : false ,
2023-03-04 22:53:12 +01:00
disable _slugify : false ,
2022-12-14 17:31:03 +01:00
reallySendPost ,
2022-08-08 16:17:04 +02:00
image : '' ,
2022-12-14 16:38:47 +01:00
folder _image : process . cwd ( ) + '/assets/blog_posts_medias/' ,
2022-08-05 14:57:53 +02:00
message : "Hey coucou! on est le" + nowDate ,
2022-11-22 12:47:07 +01:00
scheduled _at : "" ,
2023-03-03 15:19:09 +01:00
scheduled _at _bool : false ,
2023-03-04 22:53:12 +01:00
content _type : "text/markdown" ,
2022-12-14 16:38:47 +01:00
website : 'qzine' ,
slug : 'default_post_title' ,
2023-03-04 22:53:12 +01:00
postObject : { } ,
2022-08-05 14:57:53 +02:00
}
2022-08-08 16:17:04 +02:00
export function tokenForAuthorIsPresentInDotEnv ( author ) {
return process . env [ 'TOKEN_' + author . toUpperCase ( ) ] ;
}
2023-03-04 10:30:20 +01:00
/ * *
* create a masto fetcher instance
* @ param userNickName
* @ returns { Mastodon }
* /
2023-03-04 22:53:12 +01:00
export function createMastoFetcherWithAuthorLogin ( userNickName ) {
2023-03-04 10:30:20 +01:00
let accessToken = process . env [ 'TOKEN_' + userNickName . toUpperCase ( ) ]
const masto = new Masto ( {
access _token : accessToken ,
api _url : process . env . INSTANCE _MASTODON + '/api/v1/' ,
} ) ;
return masto ;
}
2023-03-04 22:53:12 +01:00
2022-12-14 16:38:47 +01:00
/ * *
* send post to mastodon with config
* @ param config
* @ returns { * }
* /
2022-12-07 23:15:07 +01:00
export default function sendPostMastodon ( config ) {
2022-08-05 14:57:53 +02:00
2022-12-14 18:18:34 +01:00
// console.log('send post', config.postObject.post_guid , config.postObject.guid )
2022-08-05 14:57:53 +02:00
// override defaults with input argument
config = {
... defaultConfigMasto ,
... config ,
}
2022-12-07 23:15:07 +01:00
// console.log("sendPostMastodon config", config)
2022-08-05 14:57:53 +02:00
2022-08-08 16:17:04 +02:00
if ( ! config . reallySendPost ) {
2023-03-03 15:19:09 +01:00
console . log ( "\n\n =========== le message ne sera PAS réellement posté sur le compte @" + config . author + "@" + process . env . INSTANCE _MASTODON + " =========== \n" )
2023-03-03 19:16:59 +01:00
// console.log('configPost.folder_image', config.folder_image)
console . log ( 'config' , config . message )
2022-08-08 16:17:04 +02:00
} else {
console . log ( " " )
if ( process . env . INSTANCE _MASTODON && tokenForAuthorIsPresentInDotEnv ( config . author ) ) {
let visibility = 'public' ;
let language = 'fr' ;
let sensitive = false ;
let accessToken = process . env [ 'TOKEN_' + config . author . toUpperCase ( ) ]
const masto = new Masto ( {
access _token : accessToken ,
api _url : process . env . INSTANCE _MASTODON + '/api/v1/' ,
} ) ;
2022-08-05 14:57:53 +02:00
2022-08-08 16:17:04 +02:00
let params = {
status : config . message ,
visibility ,
language ,
sensitive
}
if ( config . cw ) {
params [ 'spoiler_text' ] = config . cw
}
if ( config . scheduled _at && config . scheduled _at _bool ) {
let dateschedule = new Date ( config . scheduled _at )
params [ 'scheduled_at' ] = dateschedule . toISOString ( )
}
/ * *
* envoi sans fichier joint
* /
if ( ! config . image ) {
2023-03-03 15:19:09 +01:00
console . log ( 'pas d image dans la config' )
2022-08-08 16:17:04 +02:00
if ( config . reallySendPost ) {
masto . post ( 'statuses' , params ) . then ( rep => {
2022-12-07 23:15:07 +01:00
2022-08-08 16:17:04 +02:00
console . log ( "posté, yay!" )
} , err => {
console . error ( err )
} )
}
2022-08-05 14:57:53 +02:00
}
2022-08-08 16:17:04 +02:00
/ * *
* envoi avec fichier ,
* on doit d ' abord faire un upload du fichier ,
2022-12-14 16:47:57 +01:00
* puis relier son id de média au nouveau post .
2022-08-08 16:17:04 +02:00
* /
2022-12-14 16:47:57 +01:00
else if ( config . image ) {
2022-08-08 16:17:04 +02:00
var id ;
2023-03-20 13:49:38 +01:00
console . log ( "envoi du média" , config . image )
2022-12-07 23:15:07 +01:00
// upload new media
2023-03-20 13:49:38 +01:00
return masto . post ( 'media' , { file : fs . createReadStream ( config . image ) } )
2022-12-07 23:15:07 +01:00
. then ( resp => {
id = resp . data . id ;
params . media _ids = [ id ]
2022-12-14 17:31:03 +01:00
console . log ( "\n ✅ image, id" , id )
2022-12-07 23:15:07 +01:00
masto . post ( 'statuses' , params ) . then ( rep => {
// console.log('rep', rep)
2022-12-14 17:31:03 +01:00
console . log ( "\n ✅ posté avec une nouvelle image, WOOT" )
2022-12-07 23:15:07 +01:00
} , err => {
console . error ( err )
console . log ( "erreur T_T" )
2022-08-08 16:17:04 +02:00
} )
2022-12-07 23:15:07 +01:00
} )
}
2022-08-08 16:17:04 +02:00
2022-08-08 16:30:55 +02:00
// }
2022-08-08 16:17:04 +02:00
} else {
console . error ( ` pas de token pour l'auteur " ${ config . author } " ou pas d'instance mastodon définie ` )
}
2022-08-05 14:57:53 +02:00
}
}
2022-12-14 16:38:47 +01:00
// Slugify a string
2023-03-04 22:53:12 +01:00
export function slugify ( str ) {
2022-12-14 16:38:47 +01:00
str = str . replace ( /^\s+|\s+$/g , '' ) ;
// Make the string lowercase
str = str . toLowerCase ( ) ;
// Remove accents, swap ñ for n, etc
var from = "ÁÄÂÀÃÅČÇĆĎÉĚËÈÊẼĔȆÍÌÎÏŇÑÓÖÒÔÕØŘŔŠŤÚŮÜÙÛÝŸŽáäâàãåčçćďéěëèêẽĕȇíìîïňñóöòôõøðřŕšťúůüùûýÿžþÞĐđßÆa·/_,:;" ;
2023-03-04 22:53:12 +01:00
var to = "AAAAAACCCDEEEEEEEEIIIINNOOOOOORRSTUUUUUYYZaaaaaacccdeeeeeeeeiiiinnooooooorrstuuuuuyyzbBDdBAa------" ;
for ( var i = 0 , l = from . length ; i < l ; i ++ ) {
2022-12-14 16:38:47 +01:00
str = str . replace ( new RegExp ( from . charAt ( i ) , 'g' ) , to . charAt ( i ) ) ;
}
// Remove invalid chars
str = str . replace ( /[^a-z0-9 -]/g , '' )
// Collapse whitespace and replace by -
. replace ( /\s+/g , '-' )
// Collapse dashes
. replace ( /-+/g , '-' ) ;
return str ;
}
2022-08-08 22:49:12 +02:00
/ * *
* @ name listFilesOfFolder
* lister les noms de fichier que l ' on peut publier dans un dossier .
* retourne un tableau
* /
2022-12-07 23:15:07 +01:00
export function listFilesOfFolder ( folderPath ) {
2022-08-08 22:49:12 +02:00
let filesNames = [ ]
fs . readdirSync ( folderPath ) . map ( fileName => {
return filesNames . push ( fileName ) ;
} ) ;
return filesNames ;
}
2022-08-05 14:57:53 +02:00
2022-08-08 22:49:12 +02:00
/ * *
* @ name initializeFolderForPictures
* crée un dossier d ' assets , avec ses sous dossiers not _published et published si ils manquent .
* une fois que l ' on prendra une image dans le dossier non publié , on la déplacera dans le dossier des images publées .
* /
2022-12-07 23:15:07 +01:00
export function initializeFolderForPictures ( folderName ) {
2022-08-08 22:49:12 +02:00
try {
if ( ! fs . existsSync ( folderName ) ) {
fs . mkdirSync ( folderName ) ;
}
} catch ( err ) {
console . error ( err ) ;
}
2022-11-22 10:55:11 +01:00
}
2022-12-07 23:15:07 +01:00
/ * *
* find first image in blog post and return the src value of the img tag
* @ param htmlContent
* @ returns { string }
* /
2023-03-04 22:53:12 +01:00
export function findFirstImageInContent ( htmlContent = '' ) {
2022-12-07 23:15:07 +01:00
let result = ''
2022-12-14 16:38:47 +01:00
let foundPictures = htmlContent . match ( /<img\s[^>]*?src\s*=\s*['\"]([^'\"]*?)['\"][^>]*?>/ ) ;
let first = '' ;
2023-03-04 22:53:12 +01:00
if ( foundPictures && foundPictures [ 0 ] ) {
2022-12-14 16:38:47 +01:00
2023-03-04 22:53:12 +01:00
first = foundPictures [ 0 ]
2022-12-14 16:38:47 +01:00
2023-03-04 22:53:12 +01:00
} else {
2022-12-14 16:38:47 +01:00
console . log ( 'pas d image trouvée dans le contenu ' , htmlContent )
}
2022-12-07 23:15:07 +01:00
if ( first ) {
result = first . match ( /src\=\"(.*)\"/i )
2023-03-04 22:53:12 +01:00
if ( result . length && result [ 0 ] ) {
result = result [ 0 ] . split ( '"' )
result = result [ 1 ]
2022-12-07 23:15:07 +01:00
}
2022-11-22 11:27:54 +01:00
}
2022-12-14 16:38:47 +01:00
result = clearLink ( result )
console . log ( 'clearLink' , result )
2022-12-07 23:15:07 +01:00
return result ;
}
2023-03-04 22:53:12 +01:00
function clearLink ( linkString ) {
2022-12-14 16:38:47 +01:00
linkString = linkString . replace ( 'http:' , 'https:' )
linkString = linkString . replace ( 'https://www.ailesse.info/~tykayn/bazar/kotlife' , 'https://www.tykayn.fr/wp-content/uploads/i/kotlife' )
linkString = linkString . replace ( 'https://blog.artlemoine.com/public/i' , 'https://www.tykayn.fr/wp-content/uploads/i' )
2022-12-14 16:47:57 +01:00
linkString = linkString . replace ( 'https://www.ailesse.com/%7Etykayn/bazar' , 'https://www.tykayn.fr/wp-content/uploads/i/bazar' )
2022-12-14 16:38:47 +01:00
return linkString
}
2023-03-04 22:53:12 +01:00
2022-12-07 23:15:07 +01:00
/ * *
* usage :
* downloadImage ( 'https://upload.wikimedia.org/wikipedia/en/thumb/7/7d/Lenna_%28test_image%29.png/440px-Lenna_%28test_image%29.png' , 'lena.png' )
* . then ( console . log )
* . catch ( console . error ) ;
* @ param url
* @ param filepath
* @ returns { Promise < unknown > }
* /
export function downloadImage ( url , filepath ) {
return new Promise ( ( resolve , reject ) => {
2022-12-14 18:18:34 +01:00
const options = {
2023-03-04 22:53:12 +01:00
headers : { "User-Agent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.52" }
2022-12-14 18:18:34 +01:00
} ;
2023-03-04 22:53:12 +01:00
https . get ( url , options , ( res ) => {
2022-12-07 23:15:07 +01:00
if ( res . statusCode === 200 ) {
res . pipe ( fs . createWriteStream ( filepath ) )
. on ( 'error' , reject )
. once ( 'close' , ( ) => resolve ( filepath ) ) ;
} else {
// Consume response data to free up memory
res . resume ( ) ;
reject ( new Error ( ` Request Failed With a Status Code: ${ res . statusCode } ; \n ${ res . statusMessage } ` ) ) ;
}
} ) ;
} ) ;
}
/ * *
* faire un
* @ param pictureName
* @ param width
* @ param height
* @ returns { Promise < Object > }
* @ constructor
* /
2023-03-03 15:19:09 +01:00
export function CropPicture ( pictureName , width = 500 , height = 300 ) {
2022-12-07 23:15:07 +01:00
return sharp ( pictureName )
. extract ( { left : 0 , top : 0 , width , height } )
. toFile ( 'thumb_' + pictureName , function ( err ) {
if ( err ) console . log ( err ) ;
} ) ;
2022-12-14 16:38:47 +01:00
}
2023-03-04 22:53:12 +01:00
2022-12-14 16:38:47 +01:00
/ * *
* prendre un post parmi tous ceux du blog , dans ceux qui ont été publiés
* @ returns { * }
* /
export function getRandomLinkGeneral ( tkpostsjson ) {
let filteredLinks = [ ]
if ( tkpostsjson [ 0 ] . post _status ) {
filteredLinks = tkpostsjson . filter ( elem => elem . post _status === 'publish' )
} else if ( tkpostsjson [ 0 ] . status ) {
filteredLinks = tkpostsjson . filter ( elem => elem . status === 'publish' )
}
return getRandomElementOfArray ( filteredLinks )
}
/ * *
* trouver l ' image du contenu si il y en a
* @ param postContent
* @ param configPost
* /
2023-03-04 22:53:12 +01:00
export function findPictureAndSendPost ( postContent , configPost ) {
2022-12-14 16:38:47 +01:00
let firstPictureSource = findFirstImageInContent ( postContent ) ;
2023-03-03 15:19:09 +01:00
let filePathForDownloadedImage = ` ${ configPost . folder _image } _ ${ configPost . website } _media_post_ ${ slugify ( configPost . slug ) } .jpg `
2022-12-14 16:38:47 +01:00
if ( firstPictureSource ) {
console . log ( "firstPictureSource found" , firstPictureSource )
2022-12-14 17:31:03 +01:00
// check if picture already exist
2023-03-04 22:53:12 +01:00
console . log ( 'on envoie le média et l image : ' , filePathForDownloadedImage )
downloadImage ( firstPictureSource , filePathForDownloadedImage )
2022-12-14 16:38:47 +01:00
. then ( ( res ) => {
// suite du poste avec upload d'image
2022-12-14 17:31:03 +01:00
console . log ( 'média téléchargé, on envoie le post' )
2023-03-03 15:19:09 +01:00
configPost . image = filePathForDownloadedImage ;
2022-12-14 16:38:47 +01:00
sendPostMastodon ( configPost )
} ,
( err ) => {
console . log ( 'pas dimage trouvée pour l URL ' , firstPictureSource , err )
sendPostMastodon ( configPost )
}
)
. catch ( ( err ) => {
console . log ( 'erreur avec cette URL ' , firstPictureSource , err )
sendPostMastodon ( configPost )
} )
} else {
// no image provided
console . log ( "pas d'image dans le corps du texte" , configPost . image )
// on envoie avec l'image par défaut
sendPostMastodon ( configPost )
}
2022-12-14 17:31:03 +01:00
}
/ * *
* find cli argument
* @ param argument
* @ returns { boolean }
* /
2023-03-04 22:53:12 +01:00
export function hasCliArgument ( argument ) {
2022-12-14 17:31:03 +01:00
return myArgs . indexOf ( argument ) !== - 1
2023-03-03 15:19:09 +01:00
}
let parser = new Parser ( ) ;
2023-03-04 22:53:12 +01:00
export function diffDaysBetweenTwoDates ( date1 , date2 ) {
2023-03-03 17:28:41 +01:00
2023-03-03 19:16:59 +01:00
const a = moment ( date1 ) ;
const b = moment ( date2 ) ;
return a . diff ( b , 'days' ) ;
2023-03-03 17:28:41 +01:00
2023-03-03 18:54:50 +01:00
}
export function filterRegionAgendaDuLibreEvents ( events _list , filter _critera ) {
let selection = [ ]
2023-03-04 22:53:12 +01:00
events _list . forEach ( item => {
if ( item . region _id == filter _critera ) {
2023-03-03 18:54:50 +01:00
selection . push ( item )
}
} )
return selection ;
}
2023-03-03 19:16:59 +01:00
2023-03-03 18:54:50 +01:00
moment . locale ( 'fr' ) ;
2023-03-04 22:53:12 +01:00
export function groupEventsByDay ( events _list ) {
2023-03-03 18:54:50 +01:00
let selection = { }
2023-03-04 22:53:12 +01:00
events _list . forEach ( item => {
2023-03-03 18:54:50 +01:00
let formattedDay = moment ( item . start _time ) . format ( 'dddd DD' )
2023-03-04 22:53:12 +01:00
if ( ! selection [ formattedDay ] ) {
2023-03-03 18:54:50 +01:00
selection [ formattedDay ] = [ ]
}
2023-03-04 22:53:12 +01:00
selection [ formattedDay ] . push ( item )
2023-03-03 18:54:50 +01:00
} )
return selection ;
2023-03-03 17:28:41 +01:00
}