-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 06d5b1f
Showing
13 changed files
with
3,664 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
node_modules/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
Copyright 2022 Harry Tom | ||
|
||
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
# Memes Api | ||
|
||
<h1 align="center"> | ||
<br> | ||
<a href="https://bobthebot.netlify.app/"> | ||
<img src="./public/images/icon.png" alt="Bob The Bot" width="200"> | ||
</a> | ||
<br> | ||
<a href="https://instagram.com/dragshorts/">Memable API</a><br> | ||
</h1> | ||
|
||
<h4 align="center"> | ||
Memable is a Meme Explorer website (im working on) and this is a prototype of the API i created for it. It is powered by Rddit!<a href="https://instagram.com/dragshorts/">here</a> | ||
</h4> | ||
|
||
<h4 align="center"> | ||
<img src="./public/images/Reddit-Logo.png" alt="Bob The Bot" width="200"> | ||
</h4> | ||
|
||
<hr> | ||
|
||
## Table of content | ||
|
||
- [Usage](#usage) | ||
- [Endpoints](#endpoints) | ||
- [Deploy](#deploy) | ||
- [Support](#show-your-support) | ||
|
||
<br> | ||
|
||
## Usage | ||
|
||
### Clone the repo | ||
|
||
```bat | ||
git clone https://github.com/harry260/meme-api | ||
``` | ||
|
||
#### Install dependencies | ||
|
||
```bat | ||
npm install | ||
``` | ||
|
||
### Run the server | ||
|
||
```bat | ||
npm start | ||
``` | ||
|
||
<br> | ||
|
||
## Endpoints | ||
|
||
### `/memes` | ||
|
||
``` | ||
/memes?subreddits=<subreddit1>,<subreddit>:<last_post_id>&filter=<filter>&max=<max> | ||
``` | ||
|
||
| Parameter | Description | Example | | ||
| ---------- | ----------------------------------------------------------------------------------------- | ----------------------------------------------------- | | ||
| subreddits | Comma separated list of subreddits. Use colon to separate if you need to set last post id | subreddits=wholesomememes:`lastIdLOL`,memes,dankmemes | | ||
| filter | Add filter (`hot`\|`top`\|`new`\|`controversial` \| `raising`) | filter=hot | | ||
| max | Maximum number of memes from each subreddit. Doesn't mean the exact count. | max=50 | | ||
|
||
```` | ||
#### Example request & response | ||
```bat | ||
/memes?subreddits=memes,dankmemes:uc569x,wholesomememes&filter=hot&max=69 | ||
```` | ||
|
||
<a href="./example-response.json"> | ||
|
||
| Example response | | ||
| ---------------- | | ||
|
||
</a> | ||
<br> | ||
|
||
## Deploy | ||
|
||
You can deploy this to either Vercel or Railway or any other hosting service. | ||
|
||
[![Deploy on Railway](https://railway.app/button.svg)](https://railway.app/new/template/JEAO4v?referralCode=Xot9yF) | ||
|
||
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fharry260%2Fmeme-api&project-name=memeable-api&repo-name=meme-api-repo) | ||
|
||
## Show your support | ||
|
||
Show your support by 🌟 Starring this repo or buy me a coffee! | ||
<br><br> | ||
<a href="https://www.buymeacoffee.com/harrytom" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 60px !important;width: 217px !important;" ></a><br> | ||
<br> |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import express from "express"; | ||
import getParameterObj from "./lib/utils.js"; | ||
import Memes from "./lib/memes.js"; | ||
import Reddit from "./lib/reddit.js"; | ||
import cors from "cors"; | ||
import packageJSON from "./package.json" assert { type: "json" }; | ||
|
||
const app = express(); | ||
const port = process.env.PORT || 4000; | ||
|
||
app.use( | ||
cors({ | ||
origin: "*", | ||
}) | ||
); | ||
|
||
app.use("/favicon.ico", express.static("public/images/icon.png")); | ||
|
||
app.get( | ||
"/memes", | ||
(req, res) => { | ||
res.setHeader("Access-Control-Allow-Origin", "*"); | ||
res.setHeader("Access-Control-Allow-Methods", "GET"); | ||
res.setHeader( | ||
"Access-Control-Allow-Headers", | ||
"X-Requested-With,content-type" | ||
); | ||
res.setHeader("Access-Control-Allow-Credentials", true); | ||
|
||
var subreddits = req.query.subreddits; | ||
var max = req.query.max; | ||
var filter = req.query.filter; | ||
var send = false; | ||
var parameters = getParameterObj(subreddits, max, filter); | ||
var meme = new Memes(parameters); | ||
|
||
meme.getMultipleSubreddits((data) => { | ||
if (send) return; | ||
send = true; | ||
res.status(200).send(data); | ||
}, parameters.lastIDs); | ||
}, | ||
cors() | ||
); | ||
|
||
app.get("/reddit/u/:user", (req, res) => { | ||
if (req.params.user) { | ||
var user = req.params.user; | ||
|
||
Reddit.getUserInfo(user).then((data) => { | ||
res.send({ success: true, data: data }); | ||
}); | ||
} else { | ||
res.send({ | ||
success: false, | ||
error: "No user specified!", | ||
}); | ||
} | ||
}); | ||
|
||
app.get("/", (req, res) => { | ||
var repoUrl = packageJSON.repository.url.startsWith("git+") | ||
? packageJSON.repository.url.slice(4) | ||
: packageJSON.repository.url; | ||
res.redirect(repoUrl); | ||
}); | ||
|
||
app.listen(port, () => { | ||
console.log(`Server is running on port ${port}`); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
import axios from "axios"; | ||
import Reddit from "./reddit.js"; | ||
|
||
class Memes { | ||
constructor(config = {}) { | ||
// Create an array of one element if parameter is passed as string | ||
if (typeof config.subreddits === "string") { | ||
config.subreddits = [config.subreddits]; | ||
} | ||
|
||
// Set maxiuum memes | ||
this.max = config.max ?? 10; | ||
|
||
var availableFilters = ["top", "hot", "new", "controversial", "rising"]; | ||
|
||
this.filter = availableFilters.includes(config.filter) | ||
? config.filter | ||
: false; | ||
|
||
// Set the subreddit | ||
this.subreddits = config.subreddits ?? [ | ||
"memes", | ||
"dankmemes", | ||
"wholesomememes", | ||
]; | ||
} | ||
|
||
getMultipleSubreddits(callback, lastIds = {}) { | ||
var subreddits = this.subreddits; | ||
var result = {}; | ||
|
||
console.log("Fetching data from subreddits: ", subreddits); | ||
subreddits.forEach((subreddit, index) => { | ||
var last = lastIds[subreddit] ?? false; | ||
var processedRedditcount = index + 1; | ||
|
||
this.getSubreddit( | ||
subreddit, | ||
(data) => { | ||
result[subreddit] = data; | ||
if (processedRedditcount === subreddits.length) { | ||
var finalResult = { | ||
success: true, | ||
data: result, | ||
properties: { | ||
subreddits: subreddits, | ||
max: this.max, | ||
filter: this.filter, | ||
}, | ||
}; | ||
|
||
this._callback(callback, finalResult); | ||
} | ||
}, | ||
last | ||
); | ||
}); | ||
} | ||
|
||
getSubreddit(subreddit, callback, lastid) { | ||
var memes = []; | ||
var url = this._getApiUrl(subreddit, lastid); | ||
|
||
this._fetchData(url, (result) => { | ||
var data = result.data; | ||
var processeMemeCount = 0; | ||
|
||
if (result.success) { | ||
data.map((meme) => { | ||
processeMemeCount++; | ||
meme = meme.data; | ||
|
||
if (!meme.url.endsWith(".jpg")) { | ||
return; | ||
} | ||
var memeResult = { | ||
id: meme.id, | ||
title: meme.title, | ||
url: meme.url, | ||
subreddit: meme.subreddit, | ||
ups: meme.ups, | ||
downs: meme.downs, | ||
score: meme.score, | ||
created: meme.created, | ||
NSFW: meme.over_18, | ||
spoiler: meme.spoiler, | ||
permalink: meme.permalink, | ||
}; | ||
|
||
Reddit.getUserInfo(meme.author).then((authorResult) => { | ||
authorResult = authorResult.data; | ||
var sr = authorResult.subreddit || {}; | ||
|
||
var name = sr.title; | ||
var profile = sr.icon_img; | ||
var id = authorResult.name; | ||
var description = | ||
sr.public_description ?? "I love reddit!"; | ||
|
||
memeResult.author = { | ||
name, | ||
profile, | ||
id, | ||
description, | ||
}; | ||
|
||
memes.push(memeResult); | ||
if (processeMemeCount === data.length) { | ||
this._callback(callback, memes); | ||
} | ||
}); | ||
}); | ||
} | ||
}); | ||
} | ||
|
||
_getAuthorInfo(author, callback) { | ||
this._fetchData( | ||
`https://www.reddit.com/user/${author}/about.json`, | ||
(result) => { | ||
if (result.error === 404) { | ||
this._callback(callback, { | ||
success: false, | ||
error: "User not found!", | ||
}); | ||
} else { | ||
this._callback(callback, { | ||
success: true, | ||
data: result.data, | ||
}); | ||
} | ||
} | ||
); | ||
} | ||
|
||
_fetchData(url, cb) { | ||
axios | ||
.get(url) | ||
.then((response) => { | ||
const data = response.data.data.children; | ||
if (data.length === 0) { | ||
cb({ | ||
success: false, | ||
data: "No such subreddit, or it may be private!", | ||
}); | ||
} else { | ||
cb({ | ||
success: true, | ||
data: data, | ||
}); | ||
} | ||
}) | ||
.catch((error) => console.log(error)); | ||
} | ||
|
||
_callback(e, t) { | ||
var data = t ?? {}; | ||
const cb = e ?? false; | ||
if (typeof cb === "function") { | ||
cb(data); | ||
} | ||
} | ||
|
||
_getApiUrl(subreddit, lId) { | ||
var filter = this.filter; | ||
|
||
if (subreddit) { | ||
var params = {}; | ||
|
||
if (lId) { | ||
params.after = lId; | ||
} | ||
params.limit = this.max; | ||
|
||
const sp = new URLSearchParams(params); | ||
|
||
var url = `https://www.reddit.com/r/${subreddit}${ | ||
filter ? `/${filter}` : "" | ||
}.json?${sp}`; | ||
|
||
console.log("Fetching data from URL: ", url); | ||
return url; | ||
} else { | ||
return `https://www.reddit.com/r/memes.json?${this.max}`; | ||
} | ||
} | ||
} | ||
|
||
export default Memes; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import axios from "axios"; | ||
|
||
const Reddit = { | ||
getUserInfo: (username) => { | ||
if (username === "[deleted]") { | ||
var deletedInfo = { | ||
data: { | ||
subreddit: { | ||
title: "Deleted User", | ||
icon_img: "https://www.redditstatic.com/icon.png", | ||
public_description: "This user has been deleted.", | ||
}, | ||
name: "[deleted]", | ||
}, | ||
}; | ||
|
||
return new Promise(function (resolve, reject) { | ||
resolve(deletedInfo); | ||
}); | ||
} | ||
|
||
var url = `https://www.reddit.com/user/${username}/about.json`; | ||
return axios.get(url).then((response) => { | ||
return response.data; | ||
}); | ||
}, | ||
}; | ||
|
||
export default Reddit; |
Oops, something went wrong.