mirror of
https://github.com/oceanprotocol/community-numbers.git
synced 2024-11-23 10:26:54 +01:00
initial commit 🐚
This commit is contained in:
commit
e6109413aa
13
.editorconfig
Normal file
13
.editorconfig
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
# EditorConfig is awesome: http://EditorConfig.org
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.json]
|
||||
indent_size = 2
|
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
node_modules
|
||||
npm-debug.log
|
||||
yarn.lock
|
||||
package-lock.json
|
3
.nowignore
Normal file
3
.nowignore
Normal file
@ -0,0 +1,3 @@
|
||||
media/
|
||||
test/
|
||||
package-lock.json
|
5
.travis.yml
Normal file
5
.travis.yml
Normal file
@ -0,0 +1,5 @@
|
||||
language: node_js
|
||||
node_js: node
|
||||
|
||||
notifications:
|
||||
email: false
|
21
LICENSE
Executable file
21
LICENSE
Executable file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 BigchainDB GmbH
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
81
README.md
Normal file
81
README.md
Normal file
@ -0,0 +1,81 @@
|
||||
[![banner](https://raw.githubusercontent.com/oceanprotocol/art/master/github/repo-banner%402x.png)](https://oceanprotocol.com)
|
||||
|
||||
<h1 align="center">community-numbers</h1>
|
||||
|
||||
> Microservice to cache and expose community numbers for use throughout [oceanprotocol.com](https://oceanprotocol.com).
|
||||
|
||||
[![Build Status](https://travis-ci.com/oceanprotocol/community-numbers.svg?branch=master)](https://travis-ci.com/oceanprotocol/community-numbers)
|
||||
[![js oceanprotocol](https://img.shields.io/badge/js-oceanprotocol-7b1173.svg)](https://github.com/oceanprotocol/eslint-config-oceanprotocol)
|
||||
[![Greenkeeper badge](https://badges.greenkeeper.io/oceanprotocol/community-numbers.svg)](https://greenkeeper.io/)
|
||||
<img src="http://forthebadge.com/images/badges/powered-by-electricity.svg" height="20"/>
|
||||
<img src="http://forthebadge.com/images/badges/as-seen-on-tv.svg" height="20"/>
|
||||
<img src="http://forthebadge.com/images/badges/uses-badges.svg" height="20"/>
|
||||
|
||||
## API
|
||||
|
||||
Endpoint: [`https://oceanprotocol-community.now.sh`](https://oceanprotocol-community.now.sh)
|
||||
|
||||
### GET /
|
||||
|
||||
**200**: Returns a list of network numbers as follows:
|
||||
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"github": {
|
||||
"stars": 1000,
|
||||
"repos": 1000
|
||||
},
|
||||
"medium": {
|
||||
"followers": 1000
|
||||
},
|
||||
"bounties": {
|
||||
"gitcoin": 1000,
|
||||
"bountiesNetwork": 1000,
|
||||
"total": 1000
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
Install dependencies:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
And run the server:
|
||||
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
## Test
|
||||
|
||||
Run the tests:
|
||||
|
||||
```bash
|
||||
npm test
|
||||
```
|
||||
|
||||
## Deployment
|
||||
|
||||
Deploy to [now](https://zeit.co/now), make sure to switch to Ocean Protocol org before deploying:
|
||||
|
||||
```bash
|
||||
# first run
|
||||
now login
|
||||
now switch
|
||||
|
||||
# deploy
|
||||
now
|
||||
# switch alias to new deployment
|
||||
now alias
|
||||
```
|
||||
|
||||
## Authors
|
||||
|
||||
- Matthias Kretschmann ([@kremalicious](https://github.com/kremalicious)) - [Ocean Protocol](https://oceanprotocol.com)
|
40
index.js
Normal file
40
index.js
Normal file
@ -0,0 +1,40 @@
|
||||
const ms = require('ms')
|
||||
const { logError } = require('./util/logger')
|
||||
|
||||
const fetchGitHubRepos = require('./networks/github')
|
||||
const fetchBounties = require('./networks/bounties')
|
||||
const fetchMedium = require('./networks/medium')
|
||||
|
||||
let cacheGithub = null
|
||||
let cacheBounties = null
|
||||
let cacheMedium = null
|
||||
|
||||
//
|
||||
// Create the response
|
||||
//
|
||||
module.exports = async (req, res) => {
|
||||
res.setHeader('Access-Control-Allow-Origin', '*')
|
||||
res.setHeader('Access-Control-Allow-Methods', 'GET')
|
||||
|
||||
try {
|
||||
if (!cacheGithub || Date.now() - cacheGithub.lastUpdate > ms('5m')) {
|
||||
cacheGithub = await fetchGitHubRepos()
|
||||
}
|
||||
|
||||
if (!cacheBounties || Date.now() - cacheBounties.lastUpdate > ms('5m')) {
|
||||
cacheBounties = await fetchBounties()
|
||||
}
|
||||
|
||||
if (!cacheMedium || Date.now() - cacheMedium.lastUpdate > ms('5m')) {
|
||||
cacheMedium = await fetchMedium()
|
||||
}
|
||||
} catch (error) {
|
||||
logError(error.message)
|
||||
}
|
||||
|
||||
res.end(JSON.stringify({
|
||||
github: cacheGithub,
|
||||
bounties: cacheBounties,
|
||||
medium: cacheMedium
|
||||
}))
|
||||
}
|
62
networks/bounties.js
Normal file
62
networks/bounties.js
Normal file
@ -0,0 +1,62 @@
|
||||
const fetch = require('node-fetch')
|
||||
const { log, logError } = require('../util/logger')
|
||||
|
||||
const getGitcoin = async () => {
|
||||
const response = await fetch('https://gitcoin.co/api/v0.1/bounties/?&org=oceanprotocol&is_open=true')
|
||||
|
||||
if (response.status !== 200) {
|
||||
logError(`Non-200 response code from Gitcoin: ${response.status}`)
|
||||
return null
|
||||
}
|
||||
|
||||
const gitcoin = await response.json() // returns only open bounties by default
|
||||
|
||||
return gitcoin.length
|
||||
}
|
||||
|
||||
const getBountiesNetwork = async () => {
|
||||
const response = await fetch('https://api.bounties.network/bounty/?search=ocean%20protocol&bountyStage=1&platform=bounties-network')
|
||||
|
||||
if (response.status !== 200) {
|
||||
logError(`Non-200 response code from Bounties Network: ${response.status}`)
|
||||
return null
|
||||
}
|
||||
|
||||
const bountiesNetwork = await response.json()
|
||||
|
||||
return bountiesNetwork.results.length
|
||||
}
|
||||
|
||||
const getTotal = async () => {
|
||||
const response = await fetch('https://api.bounties.network/bounty/?search=ocean%20protocol')
|
||||
|
||||
if (response.status !== 200) {
|
||||
logError(`Non-200 response code from Bounties Network: ${response.status}`)
|
||||
return null
|
||||
}
|
||||
|
||||
const allBounties = await response.json()
|
||||
|
||||
return allBounties.count
|
||||
}
|
||||
|
||||
const fetchBounties = async () => {
|
||||
const start = Date.now()
|
||||
const gitcoin = await getGitcoin()
|
||||
const bountiesNetwork = await getBountiesNetwork()
|
||||
const total = await getTotal()
|
||||
|
||||
log(
|
||||
`Re-built bounties cache. ` +
|
||||
`Total: ${total} bounties. ` +
|
||||
`Elapsed: ${new Date() - start}ms`
|
||||
)
|
||||
|
||||
return {
|
||||
gitcoin,
|
||||
bountiesNetwork,
|
||||
total
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = fetchBounties
|
51
networks/github.js
Executable file
51
networks/github.js
Executable file
@ -0,0 +1,51 @@
|
||||
const fetch = require('node-fetch')
|
||||
const { log, logError } = require('../util/logger')
|
||||
|
||||
// Request options for all fetch calls
|
||||
const options = {
|
||||
headers: {
|
||||
// For getting topics, see note on https://developer.github.com/v3/search/
|
||||
// Accept: 'application/vnd.github.mercy-preview+json'
|
||||
Accept: 'application/vnd.github.preview'
|
||||
}
|
||||
}
|
||||
|
||||
const arrSum = arr => arr.reduce((a, b) => a + b, 0)
|
||||
|
||||
//
|
||||
// Fetch all public GitHub repos
|
||||
//
|
||||
const fetchGitHubRepos = async () => {
|
||||
const url = 'https://api.github.com/orgs/oceanprotocol/repos?type=public&per_page=200'
|
||||
const start = Date.now()
|
||||
const response = await fetch(url, options)
|
||||
|
||||
if (response.status !== 200) {
|
||||
logError(`Non-200 response code from GitHub: ${response.status}`)
|
||||
return null
|
||||
}
|
||||
|
||||
const json = await response.json()
|
||||
|
||||
let numbers = []
|
||||
|
||||
json.map(item => {
|
||||
if (item.stargazers_count) {
|
||||
return numbers.push(item.stargazers_count)
|
||||
}
|
||||
return null
|
||||
})
|
||||
|
||||
const stars = arrSum(numbers)
|
||||
const repositories = json.length
|
||||
|
||||
log(
|
||||
`Re-built github cache. ` +
|
||||
`Total: ${repositories} public projects with a total of ${stars} stargazers. ` +
|
||||
`Elapsed: ${new Date() - start}ms`
|
||||
)
|
||||
|
||||
return { stars, repositories }
|
||||
}
|
||||
|
||||
module.exports = fetchGitHubRepos
|
29
networks/medium.js
Normal file
29
networks/medium.js
Normal file
@ -0,0 +1,29 @@
|
||||
const fetch = require('node-fetch')
|
||||
const { log, logError } = require('../util/logger')
|
||||
|
||||
const fetchMedium = async () => {
|
||||
const url = 'https://medium.com/oceanprotocol?format=json'
|
||||
const start = Date.now()
|
||||
const response = await fetch(url)
|
||||
|
||||
if (response.status !== 200) {
|
||||
logError(`Non-200 response code from Medium: ${response.status}`)
|
||||
return null
|
||||
}
|
||||
|
||||
const responseText = await response.text()
|
||||
const json = await JSON.parse(responseText.replace('])}while(1);</x>', ''))
|
||||
const { collection } = json.payload
|
||||
|
||||
const followers = collection.metadata.followerCount
|
||||
|
||||
log(
|
||||
`Re-built medium cache. ` +
|
||||
`Total: ${followers} followers. ` +
|
||||
`Elapsed: ${new Date() - start}ms`
|
||||
)
|
||||
|
||||
return { followers }
|
||||
}
|
||||
|
||||
module.exports = fetchMedium
|
14
now.json
Normal file
14
now.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"version": 2,
|
||||
"name": "oceanprotocol-community",
|
||||
"alias": "oceanprotocol-community.now.sh",
|
||||
"env": {
|
||||
"NODE_ENV": "production"
|
||||
},
|
||||
"builds": [
|
||||
{
|
||||
"src": "index.js",
|
||||
"use": "@now/node"
|
||||
}
|
||||
]
|
||||
}
|
23
package.json
Normal file
23
package.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "@oceanprotocol/community-numbers",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "micro",
|
||||
"dev": "micro-dev",
|
||||
"test": "eslint --ignore-path .gitignore --ext .js,.jsx ."
|
||||
},
|
||||
"dependencies": {
|
||||
"chalk": "2.4.2",
|
||||
"micro": "^9.3.4",
|
||||
"ms": "^2.1.1",
|
||||
"node-fetch": "2.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^5.16.0",
|
||||
"eslint-config-oceanprotocol": "^1.3.0",
|
||||
"eslint-plugin-node": "^9.0.1",
|
||||
"micro-dev": "^3.0.0"
|
||||
}
|
||||
}
|
7
util/logger.js
Normal file
7
util/logger.js
Normal file
@ -0,0 +1,7 @@
|
||||
/* eslint-disable no-console */
|
||||
const chalk = require('chalk')
|
||||
|
||||
const log = text => console.log(text)
|
||||
const logError = text => console.log(chalk.bold.red(text))
|
||||
|
||||
module.exports = { log, logError }
|
Loading…
Reference in New Issue
Block a user