mirror of
https://github.com/Akif9748/akf-forum.git
synced 2024-12-22 23:59:08 +03:00
Added API. And META informations are fixed
This commit is contained in:
parent
40b5126b9d
commit
bde409a702
21 changed files with 317 additions and 45 deletions
73
APIDOCS.md
Normal file
73
APIDOCS.md
Normal file
|
@ -0,0 +1,73 @@
|
|||
# API documentation of Akf-forum
|
||||
<img src="https://raw.githubusercontent.com/Akif9748/akf-forum/main/public/images/logo.jpg" align="right" width="300px" />
|
||||
|
||||
Akf-forum has got an API for other clients etc.
|
||||
|
||||
You can find an example in apitest.py.
|
||||
|
||||
## Authorization
|
||||
You need this headers for send request to API:
|
||||
```jsonc
|
||||
{
|
||||
"username": "testUser",
|
||||
"password": "testPassword"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## How to request?
|
||||
|
||||
### Request type:
|
||||
`GET /api/action/id`
|
||||
|
||||
### "action" types:
|
||||
- `message`
|
||||
|
||||
(for now, only message.)
|
||||
|
||||
### "id":
|
||||
ID for action type.
|
||||
|
||||
|
||||
### Example request:
|
||||
```GET /api/message/1```
|
||||
|
||||
#### Example API Output:
|
||||
```json
|
||||
{
|
||||
"status": 200,
|
||||
"result":
|
||||
{
|
||||
"content": "First message",
|
||||
"time": 1647178873587,
|
||||
"deleted": false,
|
||||
"edited": false,
|
||||
"react": {},
|
||||
"id": 1,
|
||||
"author": {
|
||||
"name": "ForumcuCocuk",
|
||||
"avatar": "/images/guest.png",
|
||||
"time": 1647177723873,
|
||||
"admin": true,
|
||||
"id": 1
|
||||
},
|
||||
"thread": {
|
||||
"author": {
|
||||
"name": "Akif9748",
|
||||
"avatar": "/images/guest.png",
|
||||
"time": 1647177705200,
|
||||
"admin": true,
|
||||
"id": 0
|
||||
},
|
||||
"title": "First Thread",
|
||||
"messages": [0, 1],
|
||||
"time": 1647178870047,
|
||||
"deleted": false,
|
||||
"id": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
29
README.md
29
README.md
|
@ -8,14 +8,16 @@ A forum script written in Node.js.
|
|||
- Write `npm i` to install **dependencies**.
|
||||
- Write `npm restart` for reset database, and `npm start` for run it.
|
||||
|
||||
## API
|
||||
Akf-forum has got an API for other clients etc. You can test api with run apitest.py.
|
||||
And, you can learn informations about API in `APIDOCS.md`.
|
||||
|
||||
## Credits
|
||||
* [Akif9748](https://github.com/Akif9748) - Project owner
|
||||
* [Akif9748](https://github.com/Akif9748) - Project owner, main developer
|
||||
* [Camroku](https://github.com/Camroku) - Made stylesheets
|
||||
|
||||
|
||||
|
||||
## To Do:
|
||||
- Admin panel, delete, edit messages.
|
||||
- Better method for params in URL
|
||||
|
||||
## Roadmap
|
||||
- [x] User
|
||||
|
@ -26,22 +28,21 @@ A forum script written in Node.js.
|
|||
- [x] Message count
|
||||
- [x] Delete User
|
||||
- [ ] Singature & About me
|
||||
- [ ] Edit user
|
||||
- [ ] Messages
|
||||
- [x] Send message
|
||||
- [x] Delete message
|
||||
- [ ] Edit message
|
||||
- [x] React message
|
||||
- [ ] Forums
|
||||
- [ ] Category system
|
||||
- [ ] Create category
|
||||
- [ ] Delete category
|
||||
- [ ] Edit category
|
||||
- [ ] Move category
|
||||
- [ ] Threads
|
||||
- [ ] Edit it!
|
||||
- [ ] Delete it!
|
||||
- [ ] Other
|
||||
- [ ] API
|
||||
- [ ] Other client for forum via API
|
||||
- [ ] Footer...
|
||||
- [ ] Search
|
||||
- [x] API
|
||||
- [x] Other client for forum via API
|
||||
- [ ] Footer of the site
|
||||
- [ ] Multiple theme support
|
||||
- [ ] Search
|
||||
- [x] New Thread theme, better render for messages
|
||||
## Image:
|
||||
![image](https://user-images.githubusercontent.com/70021050/158060900-7384d394-cad7-4f73-94ad-7c8bd108ac44.png)
|
||||
|
|
81
api/index.js
Normal file
81
api/index.js
Normal file
|
@ -0,0 +1,81 @@
|
|||
const { User, Message, Thread } = require("../classes");
|
||||
const db = require("quick.db");
|
||||
|
||||
|
||||
class ApiResponse {
|
||||
constructor(status, result) {
|
||||
this.status = status;
|
||||
this.result = result;
|
||||
}
|
||||
}
|
||||
|
||||
const { request, response } = require("express");
|
||||
|
||||
/**
|
||||
* For intellisense
|
||||
* @param {request} req
|
||||
* @param {response} res
|
||||
*/
|
||||
|
||||
module.exports = (req, res) => {
|
||||
|
||||
const error = (status, error) =>
|
||||
res.status(status).json(new ApiResponse(403, { error }))
|
||||
|
||||
|
||||
/**
|
||||
* AUTH TYPE:
|
||||
|
||||
headers:
|
||||
{
|
||||
username: "Username for client",
|
||||
password: "Password of selected username for client"
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
const { username = null, password = null } = req.headers;
|
||||
|
||||
if (!username || !password)
|
||||
return error(403, "Headers are missing")
|
||||
|
||||
const user = db.get("secret." + username);
|
||||
|
||||
if (!user)
|
||||
return error(403, "We have not got any user has got this name")
|
||||
|
||||
if (user.key !== password)
|
||||
return error(403, 'Incorrect Password!')
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* REQUEST TYPE:
|
||||
* GET /api/action/id
|
||||
*
|
||||
* @example message action:
|
||||
* GET /api/message/0
|
||||
*
|
||||
*/
|
||||
const { action } = req.params;
|
||||
|
||||
switch (action) {
|
||||
case "message":
|
||||
const { id = null } = req.params;
|
||||
if (!id) return error(403, "Missing id in query")
|
||||
const message = new Message().getId(id);
|
||||
|
||||
if (!message || message.deleted) return error(403, "We have not got any message declared as this id.");
|
||||
|
||||
res.status(200).json(new ApiResponse(200, message));
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return error(403, "Missing/undefined param: action");
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
50
apitest.py
Normal file
50
apitest.py
Normal file
|
@ -0,0 +1,50 @@
|
|||
import requests
|
||||
|
||||
# Headers for login to Akf-forum
|
||||
headers = {
|
||||
"username": "testUser",
|
||||
"password": "testPassword"
|
||||
}
|
||||
|
||||
|
||||
r = requests.get("http://localhost:3000/api/message/1/", headers=headers)
|
||||
|
||||
print(r.json())
|
||||
|
||||
example_response = {
|
||||
"status": 200,
|
||||
"result":
|
||||
{ # content of message
|
||||
"content": "a",
|
||||
# author of message
|
||||
"author": {
|
||||
"name": "ForumcuCocuk",
|
||||
"avatar": "/images/guest.png",
|
||||
"time": 1647177723873,
|
||||
"admin": True,
|
||||
"id": 1
|
||||
},
|
||||
# UNIX Timestamp of message
|
||||
"time": 1647178873587,
|
||||
# thread information of message
|
||||
"thread": {
|
||||
"author": {
|
||||
"name": "ForumcuCocuk",
|
||||
"avatar": "/images/guest.png",
|
||||
"time": 1647177723873,
|
||||
"admin": True,
|
||||
"id": 1
|
||||
},
|
||||
"title": "My",
|
||||
"messages": [0], # ids of messages
|
||||
"time": 1647178870047,
|
||||
"deleted": False,
|
||||
"id": "0"
|
||||
},
|
||||
# Other informations about message
|
||||
"deleted": False,
|
||||
"edited": False,
|
||||
"react": {},
|
||||
"id": "1"
|
||||
}
|
||||
}
|
|
@ -1,6 +1,9 @@
|
|||
const Message = require("./message")
|
||||
const Thread = require("./thread")
|
||||
const User = require("./user")
|
||||
const React = require("./react")
|
||||
const Message = require("./message");
|
||||
const Thread = require("./thread");
|
||||
const User = require("./user");
|
||||
const React = require("./react");
|
||||
|
||||
module.exports = { Message, Thread, User, React }
|
||||
/**
|
||||
* Classes for akf-forum;
|
||||
*/
|
||||
module.exports = { Message, Thread, User, React };
|
|
@ -17,10 +17,10 @@ module.exports = class Message {
|
|||
this.react = react;
|
||||
}
|
||||
getId(id = this.id) {
|
||||
const message = db.get("messages" ).find(msg => msg.id == id);
|
||||
const message = db.get("messages").find(msg => msg.id == id);
|
||||
if (!message) return null;
|
||||
|
||||
this.id = id;
|
||||
this.id = Number(id);
|
||||
const { content, author, thread = new Thread(), time = new Date().getTime(), deleted = false, edited = false, react = {} } = message;
|
||||
this.content = content;
|
||||
this.thread = thread;
|
||||
|
|
|
@ -19,7 +19,7 @@ module.exports = class Thread {
|
|||
getId(id = this.id) {
|
||||
const thread = db.get("threads").find(t => t.id == id);
|
||||
if (!thread) return null;
|
||||
this.id = id;
|
||||
this.id = Number(id);
|
||||
const { title, author, messages = [], time = new Date().getTime(), deleted = false } = thread;
|
||||
this.title = title
|
||||
this.author = author
|
||||
|
|
10
index.js
10
index.js
|
@ -18,13 +18,19 @@ app.set("view engine", "ejs");
|
|||
//Temp:
|
||||
app.get("/", (req, res) => res.redirect("/index"));
|
||||
|
||||
/**
|
||||
* API:
|
||||
*/
|
||||
app.get("/api/:action/:id", require("./api"));
|
||||
|
||||
for (const type of fs.readdirSync("./routes"))
|
||||
for (const file of fs.readdirSync("./routes/" + type))
|
||||
app[type](`/${file.replace(".js", "")}*`, require(`./routes/${type}/${file}`))
|
||||
|
||||
app.get('*', (req, res) => error(res, 404, "We have not got this page."));
|
||||
app.post('*', (req, res) => error(res, 404, "We have not got this page."));
|
||||
app.post('*', (req, res) => error(res, 404, "We have not got this page."));
|
||||
|
||||
const port = process.env.PORT || 3000;
|
||||
|
||||
app.listen(port, () => console.log("SERVER ON PORT:", port));
|
||||
app.listen(port, () => console.log("SERVER ON PORT:", port));
|
||||
|
||||
|
|
4
package-lock.json
generated
4
package-lock.json
generated
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"name": "karum",
|
||||
"name": "akf-lang",
|
||||
"version": "2.1.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "karum",
|
||||
"name": "akf-lang",
|
||||
"version": "2.1.0",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "karum",
|
||||
"name": "akf-lang",
|
||||
"version": "2.1.0",
|
||||
"description": "A forum script written in Node.js",
|
||||
"main": "index.js",
|
||||
|
@ -9,7 +9,7 @@
|
|||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/Akif9748/karum.git"
|
||||
"url": "git+https://github.com/Akif9748/akf-lang.git"
|
||||
},
|
||||
"author": "Akif9748",
|
||||
"contributors": [
|
||||
|
@ -17,9 +17,9 @@
|
|||
],
|
||||
"license": "GPL-3.0-or-later",
|
||||
"bugs": {
|
||||
"url": "https://github.com/Akif9748/karum/issues"
|
||||
"url": "https://github.com/Akif9748/akf-lang/issues"
|
||||
},
|
||||
"homepage": "https://github.com/Akif9748/karum#readme",
|
||||
"homepage": "https://github.com/Akif9748/akf-lang#readme",
|
||||
"dependencies": {
|
||||
"body-parser": "^1.19.2",
|
||||
"ejs": "^3.1.6",
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
const { User } = require("../../classes/index");
|
||||
const { get } = require("quick.db");
|
||||
const error = require("../../errors/error.js");
|
||||
|
||||
module.exports = (req, res) => {
|
||||
|
|
9
routes/get/userEdit.js
Normal file
9
routes/get/userEdit.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
const { User } = require("../../classes/index");
|
||||
module.exports = (req, res) => {
|
||||
|
||||
if (!req.session.loggedin) return res.redirect('/login');
|
||||
|
||||
const user = new User().getId(req.session.userid);
|
||||
res.render("userEdit", { user })
|
||||
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
const db = require("quick.db");
|
||||
const error = require("../../errors/error.js")
|
||||
const { User, Message } = require("../../classes/index");
|
||||
const { User } = require("../../classes/index");
|
||||
|
||||
module.exports = (req, res) => {
|
||||
req.session.loggedin = false;
|
||||
|
@ -12,19 +12,19 @@ module.exports = (req, res) => {
|
|||
const user = db.get("secret." + username)
|
||||
if (user) {
|
||||
// Authenticate the user
|
||||
if (user.key !== password) return error(res, 404, 'Incorrect Password!')
|
||||
if (new User().getName(username).deleted) return error(res, 404, 'Incorrect Username and/or Password!')
|
||||
if (user.key !== password) return error(res, 403, 'Incorrect Password!')
|
||||
if (new User().getName(username).deleted) return error(res, 403, 'Incorrect Username and/or Password!')
|
||||
req.session.loggedin = true;
|
||||
req.session.username = username;
|
||||
req.session.userid = user.id;
|
||||
|
||||
res.redirect('/');
|
||||
} else
|
||||
error(res, 404, 'Incorrect Username and/or Password!')
|
||||
error(res, 403, 'Incorrect Username and/or Password!')
|
||||
|
||||
|
||||
} else
|
||||
error(res, 404, "You forgot entering some values")
|
||||
error(res, 403, "You forgot entering some values")
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
<link rel="stylesheet" href="/css/styles.css" />
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Main page!</title>
|
||||
<meta name="description" content="Akf-forum!">
|
||||
<title>Admin panel!</title>
|
||||
<meta name="description" content="Admin panel of Akf-forum!">
|
||||
<meta name="author" content="Akif9748">
|
||||
<link rel="icon" type="image/x-icon" href="/images/favicon.jpg">
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Main page!</title>
|
||||
<meta name="description" content="Akf-forum!">
|
||||
<meta name="description" content="Main page of Akf-forum!">
|
||||
<meta name="author" content="Akif9748">
|
||||
<link rel="icon" type="image/x-icon" href="/images/favicon.jpg">
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>LOGIN</title>
|
||||
<meta name="description" content="Akf-forum!">
|
||||
<meta name="description" content="Login to Akf-forum!">
|
||||
<meta name="author" content="Akif9748">
|
||||
<link rel="icon" type="image/x-icon" href="/images/favicon.jpg">
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Open Thread</title>
|
||||
<meta name="description" content="Akf-forum!">
|
||||
<meta name="description" content="Open thread in Akf-forum!">
|
||||
<meta name="author" content="Akif9748">
|
||||
<link rel="icon" type="image/x-icon" href="/images/favicon.jpg">
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Register</title>
|
||||
<meta name="description" content="Akf-forum!">
|
||||
<meta name="description" content="Register to Akf-forum!">
|
||||
<link rel="icon" type="image/x-icon" href="/images/favicon.jpg">
|
||||
|
||||
</head>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<title>
|
||||
<%= thread.title %>
|
||||
</title>
|
||||
<meta name="description" content="Akf-forum!">
|
||||
<meta name="description" content="Thread page of Akf-forum!">
|
||||
<meta name="author" content="Akif9748">
|
||||
<link rel="icon" type="image/x-icon" href="/images/favicon.jpg">
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
<link rel="stylesheet" href="/css/styles.css" />
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Main page!</title>
|
||||
<meta name="description" content="Akf-forum!">
|
||||
<title>Threads!</title>
|
||||
<meta name="description" content="Threads' page of Akf-forum!">
|
||||
<meta name="author" content="Akif9748">
|
||||
<link rel="icon" type="image/x-icon" href="/images/favicon.jpg">
|
||||
|
||||
|
|
50
views/userEdit.ejs
Normal file
50
views/userEdit.ejs
Normal file
|
@ -0,0 +1,50 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<link rel="stylesheet" href="/css/styles.css" />
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Edit profile</title>
|
||||
<meta name="description" content="Akf-forum!">
|
||||
<link rel="icon" type="image/x-icon" href="/images/favicon.jpg">
|
||||
|
||||
</head>
|
||||
|
||||
|
||||
<body>
|
||||
<!-- Navbar: -->
|
||||
<a href="/"><img class="logo" src="/images/logo.jpg" alt="AKF-FORUM"></a>
|
||||
<br> <button class="buyuk" onclick="window.location.href = '/threads'">THREADS</button>
|
||||
|
||||
<button class="buyuk" onclick="window.location.href = '/search'">SEARCH</button>
|
||||
<button class="buyuk" onclick="window.location.href = '/users'">USERS</button>
|
||||
<button class="buyuk" onclick="window.location.href = '/createThread/'">OPEN THREAD</button>
|
||||
<h1 style="display:inline; float:right;"><a href=<%=user.getLink() %>> <%= user.name %></a>
|
||||
<img class="yuvarlak" src=<%=user.avatar %> alt=<%= user.name %>>
|
||||
</h1>
|
||||
<hr>
|
||||
|
||||
<!-- Navbar end -->
|
||||
|
||||
<hr>
|
||||
|
||||
|
||||
|
||||
<h1>This page is not ready.</h1>
|
||||
<hr>
|
||||
<!--- <form action="/userEdit/<%= %>" method="post">
|
||||
|
||||
|
||||
<input type="text" name="username" placeholder="Username" id="username" required>
|
||||
|
||||
<input type="password" name="password" placeholder="Password" id="password" required>
|
||||
|
||||
<input type="text" name="avatar" placeholder="Avatar URL" id="avatar">
|
||||
|
||||
<input type="submit" value="Register">
|
||||
</form>
|
||||
-->
|
||||
</body>
|
||||
|
||||
</html>
|
Loading…
Reference in a new issue