first
This commit is contained in:
commit
e9d4d30f57
9
.drone.yml
Normal file
9
.drone.yml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
pipeline:
|
||||||
|
docker:
|
||||||
|
image: plugins/docker
|
||||||
|
registry: docker.mtfos.xyz
|
||||||
|
repo: docker.mtfos.xyz/mtfos/fblook
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
tags: [latest, "${DRONE_COMMIT}"]
|
||||||
|
when:
|
||||||
|
branch: release
|
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
node_modules
|
6
Dockerfile
Normal file
6
Dockerfile
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
FROM node:8-alpine
|
||||||
|
RUN apk add --no-cache curl ca-certificates
|
||||||
|
WORKDIR /data
|
||||||
|
COPY . .
|
||||||
|
RUN npm install
|
||||||
|
CMD ["npm", "start"]
|
4
config.js
Normal file
4
config.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
module.exports = {
|
||||||
|
api_url: process.env.API_URL || '',
|
||||||
|
api_key: process.env.API_KEY || ''
|
||||||
|
}
|
105
facebook-parser.js
Normal file
105
facebook-parser.js
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
const request = require('request')
|
||||||
|
const cheerio = require('cheerio')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef lastPost
|
||||||
|
* @prop {string} txt post body
|
||||||
|
* @prop {string} id post id
|
||||||
|
* @prop {string} link post link
|
||||||
|
* @prop {string} time timestamp
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* get facebook fan page last post
|
||||||
|
* @param {string} pageid facebook fan page id
|
||||||
|
* @return {Promise<lastPost>}
|
||||||
|
*/
|
||||||
|
const getLastPost = async (pageid = '') => {
|
||||||
|
if (typeof pageid !== 'string' || pageid.trim().length === 0) return null
|
||||||
|
pageid = pageid.trim()
|
||||||
|
// console.log('access facebook fan page :::: ' + pageid)
|
||||||
|
let page = await new Promise((resolve) => {
|
||||||
|
request({
|
||||||
|
baseUrl: 'https://www.facebook.com',
|
||||||
|
url: `/${encodeURIComponent(pageid)}/posts`,
|
||||||
|
method: 'get',
|
||||||
|
headers: {
|
||||||
|
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0'
|
||||||
|
}
|
||||||
|
}, (err, res, body) => {
|
||||||
|
if (err) {
|
||||||
|
resolve(null)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (body && typeof body !== 'string' && !(body instanceof String)) {
|
||||||
|
resolve(null)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resolve(body)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
if (page === null) return null
|
||||||
|
console.log(`${pageid} page length :::: `, Buffer.from(page).length)
|
||||||
|
let $ = cheerio.load(page, {
|
||||||
|
lowerCaseTags: true,
|
||||||
|
lowerCaseAttributeNames: true
|
||||||
|
})
|
||||||
|
|
||||||
|
let posts = []
|
||||||
|
|
||||||
|
$('div.userContentWrapper').each((i, el) => {
|
||||||
|
let t = cheerio.load(el)
|
||||||
|
let timeEl = t('abbr')
|
||||||
|
let time = timeEl.attr('data-utime')
|
||||||
|
let link = timeEl.parent().attr('href')
|
||||||
|
let p = t('div.userContent')
|
||||||
|
let txt = p.text() || ''
|
||||||
|
let id = p.first().attr('id')
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
if (/[\?|&]id\=(\d+)/.test(link)) { // eslint-disable-line
|
||||||
|
let m = link.match(/[\?|&]story_fbid\=(\d+)/) // eslint-disable-line
|
||||||
|
if (m !== null && m.length > 1) {
|
||||||
|
id = m[1]
|
||||||
|
}
|
||||||
|
} else if (/\/posts\/(\d+)/.test(link)) {
|
||||||
|
let m = link.match(/\/posts\/(\d+)/)
|
||||||
|
if (m !== null && m.length > 1) {
|
||||||
|
id = m[1]
|
||||||
|
}
|
||||||
|
} else if (/\/photos\/.+?\/(\d+)/.test(link)) {
|
||||||
|
let m = link.match(/\/photos\/.+?\/(\d+)/)
|
||||||
|
if (m !== null && m.length > 1) {
|
||||||
|
id = m[1]
|
||||||
|
}
|
||||||
|
} else if (/\/videos\/(\d+)/.test(link)) {
|
||||||
|
let m = link.match(/\/videos\/(\d+)/)
|
||||||
|
if (m !== null && m.length > 1) {
|
||||||
|
id = m[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// console.log(time, link, txt, id)
|
||||||
|
if (!time || !link || !id) return null
|
||||||
|
let tmp = {
|
||||||
|
txt,
|
||||||
|
id,
|
||||||
|
link,
|
||||||
|
time
|
||||||
|
}
|
||||||
|
posts.push(tmp)
|
||||||
|
el = null
|
||||||
|
t = null
|
||||||
|
})
|
||||||
|
$ = null
|
||||||
|
if (posts.length === 0) return null
|
||||||
|
posts.sort((a, b) => {
|
||||||
|
return b.time - a.time
|
||||||
|
})
|
||||||
|
let post = posts[0]
|
||||||
|
post.link = `https://www.facebook.com/${post.link.replace(/^\//, '')}`
|
||||||
|
return post
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getLastPost
|
||||||
|
}
|
83
index.js
Normal file
83
index.js
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
const cron = require('cron')
|
||||||
|
const axios = require('axios')
|
||||||
|
const config = require('./config')
|
||||||
|
const fbparser = require('./facebook-parser')
|
||||||
|
|
||||||
|
const getIDsUrl = '/api/private/pages'
|
||||||
|
const updatePostsUrl = '/api/private/pageposts'
|
||||||
|
|
||||||
|
const getIDsFromAPI = async () => {
|
||||||
|
try {
|
||||||
|
let apiResult = await axios({
|
||||||
|
baseURL: config.api_url,
|
||||||
|
url: getIDsUrl,
|
||||||
|
headers: {
|
||||||
|
'X-Mtfos-Key': config.api_key
|
||||||
|
},
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
if (!('data' in apiResult) || !('list' in apiResult.data) || !Array.isArray(apiResult.data.list)) return
|
||||||
|
apiResult.data.list.forEach(t => {
|
||||||
|
getLastPost(t)
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
console.log('get ids fail :::: ', err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getLastPost = async (id = '') => {
|
||||||
|
console.log(`Start Get ${id} Page Post`)
|
||||||
|
if (typeof id !== 'string' || id.trim().length === 0) return
|
||||||
|
id = id.trim()
|
||||||
|
|
||||||
|
try {
|
||||||
|
let lastPost = await fbparser.getLastPost(id)
|
||||||
|
if (lastPost === null) {
|
||||||
|
console.log('get post empty')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
console.log('get post ::: ', `PageID: ${id} / PostID: ${lastPost.id} / Time: ${lastPost.time} / Text: ${lastPost.txt}`)
|
||||||
|
if (!('id' in lastPost) || !('txt' in lastPost) || !('time' in lastPost) || !('link' in lastPost)) return
|
||||||
|
let minTime = Math.floor(Date.now() / 1000) - 1800
|
||||||
|
if (minTime > lastPost.time) return
|
||||||
|
let data = {
|
||||||
|
id,
|
||||||
|
post_id: lastPost.id,
|
||||||
|
text: lastPost.txt,
|
||||||
|
link: lastPost.link
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await axios({
|
||||||
|
baseURL: config.api_url,
|
||||||
|
url: updatePostsUrl,
|
||||||
|
method: 'post',
|
||||||
|
headers: {
|
||||||
|
'X-Mtfos-Key': config.api_key
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
pages: [data]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
console.log('update post data fail', err)
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log('get last post error', err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set fblook
|
||||||
|
new cron.CronJob({ //eslint-disable-line
|
||||||
|
cronTime: '00 */2 * * * *',
|
||||||
|
onTick: async () => {
|
||||||
|
console.log('Start Tick')
|
||||||
|
try {
|
||||||
|
await getIDsFromAPI()
|
||||||
|
} catch (err) {
|
||||||
|
console.log('run tick fail', err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
runOnInit: true,
|
||||||
|
start: true,
|
||||||
|
timeZone: 'Asia/Taipei'
|
||||||
|
})
|
2341
package-lock.json
generated
Normal file
2341
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
22
package.json
Normal file
22
package.json
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"name": "node-fblook",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "node index.js",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^0.18.0",
|
||||||
|
"cheerio": "^1.0.0-rc.2",
|
||||||
|
"cron": "^1.4.1",
|
||||||
|
"request": "^2.88.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"standard": "^12.0.1"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user