Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add basic Reddit setup #17

Merged
merged 6 commits into from
Nov 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 17 additions & 11 deletions .env.dist
Original file line number Diff line number Diff line change
@@ -1,33 +1,31 @@

# core settings
# app settings
FAIRPOST_UI=cli
FAIRPOST_STORAGE_SETTINGS=env
FAIRPOST_STORAGE_AUTH=env
FAIRPOST_USER_AGENT=Fairpost 1.0

# fairpost settings
# feed settings

FAIRPOST_FEED_PATH=feed
FAIRPOST_FEED_INTERVAL=6 #days

FAIRPOST_FEED_PLATFORMS=

# all platforms:
# FAIRPOST_FEED_PLATFORMS=facebook,instagram,twitter
# FAIRPOST_FEED_PLATFORMS=facebook,instagram,twitter,reddit

# ayrshare platforms:
# all ayrshare platforms:
# FAIRPOST_FEED_PLATFORMS=asyoutube,asfacebook,aslinkedin,asinstagram,astiktok,asreddit,astwitter



# oauth client used to set up platforms
FAIRPOST_CLIENT_HOSTNAME=localhost
FAIRPOST_CLIENT_PORT=8000
FAIRPOST_REQUEST_HOSTNAME=localhost
FAIRPOST_REQUEST_PORT=8000

# ayrshare
# ayrshare settings
# FAIRPOST_AYRSHARE_API_KEY=xxxx
# FAIRPOST_AYRSHARE_SUBREDDIT=xxxx


# facebook settings
# FAIRPOST_FACEBOOK_APP_ID=xxx
# FAIRPOST_FACEBOOK_APP_SECRET=xxx
Expand All @@ -52,4 +50,12 @@ FAIRPOST_CLIENT_PORT=8000
# FAIRPOST_TWITTER_O1_ACCESS_TOKEN=xxx
# FAIRPOST_TWITTER_O1_ACCESS_SECRET=xxx
# twitter auth
# FAIRPOST_TWITTER_ACCESS_TOKEN=xxx
# FAIRPOST_TWITTER_ACCESS_TOKEN=xxx

# reddit settings
# FAIRPOST_REDDIT_CLIENT_ID=xxx
# FAIRPOST_REDDIT_CLIENT_SECRET=xxx
# FAIRPOST_REDDIT_SUBREDDIT=test
# reddit auth
# FAIRPOST_REDDIT_ACCESS_TOKEN=xxx
# FAIRPOST_REDDIT_REFRESH_TOKEN=xxx
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

<img src="https://github.com/commonpike/fairpost/raw/develop/public/fairpost-icon.png" width="64" height="64">
<img src="https://github.com/commonpike/fairpost/raw/master/public/fairpost-icon.png" width="64" height="64">

# Fairpost

Expand Down
90 changes: 90 additions & 0 deletions docs/Reddit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Platform: Reddit

## Setting up the Reddit platform

### Create a new App in your Reddit account

- go to https://www.reddit.com/prefs/apps
- create an app ('script')
- redirect url with host/port from your .env (http://localhost:8000/callback)
- note the code and secret in your app box
- save as `FAIRPOST_REDDIT_CLIENT_ID` in .env
- save as `FAIRPOST_REDDIT_CLIENT_SECRET` in .env
- read the terms here https://www.reddit.com/wiki/api/#wiki_read_the_full_api_terms_and_sign_up_for_usage
- request access to the API using the request form, and wait until approved

### Enable the platform
- Add 'reddit' to your `FAIRPOST_FEED_PLATFORMS` in `.env`

### Get an OAuth2 Access Token for your Reddit account

This token last for 24 hours and should be refreshed.

- call `./fairpost.js setup-platform --platform=reddit`
- follow instructions from the command line

# Random documentation

https://www.reddit.com/r/test/

https://www.reddit.com/prefs/apps

https://www.reddit.com/wiki/api/#wiki_read_the_full_api_terms_and_sign_up_for_usage

duration permanent -> refresh
scope submit

https://github.com/reddit-archive/reddit/wiki/OAuth2

GET https://www.reddit.com/api/v1/authorize?client_id=CLIENT_ID&response_type=TYPE&
state=RANDOM_STRING&redirect_uri=URI&duration=DURATION&scope=SCOPE_STRING

POST https://www.reddit.com/api/v1/access_token
grant_type=authorization_code&code=CODE&redirect_uri=URI
Authorization: Basic Auth (client_id:client_secret)
{
"access_token": Your access token,
"token_type": "bearer",
"expires_in": Unix Epoch Seconds,
"scope": A scope string,
"refresh_token": Your refresh token
}

POST https://www.reddit.com/api/v1/access_token
grant_type=refresh_token&refresh_token=TOKEN
Authorization: Basic Auth (client_id:client_secret)


https://www.reddit.com/dev/api

https://www.reddit.com/dev/api/oauth#POST_api_submit


~~ https://github.com/reddit-archive/reddit/wiki/OAuth2

https://www.reddit.com/r/redditdev/comments/9li6le/reddit_api_how_do_i_authenticate_trying_to_do/


https://www.reddit.com/r/redditdev/comments/x53h1y/having_trouble_submitting_an_image_post/

https://github.com/rvelasq/scriptable-selig

https://github.com/rvelasq/scriptable-selig/blob/master/Selig.js#L855


https://github.com/Pyprohly/reddit-api-doc-notes/blob/main/docs/api-reference/submission.rst#upload-media

upload video
https://www.reddit.com/r/redditdev/comments/9x3a6c/comment/e9p9cet/?utm_source=share&utm_medium=web2x&context=3
https://oauth.reddit.com/api/v2/image_upload_s3.json
similar to upload emoji
https://www.reddit.com/dev/api/#POST_api_widget_image_upload_s3


https://github.com/praw-dev/praw/blob/master/praw/models/reddit/subreddit.py#L1699
"upload_image": "r/{subreddit}/api/upload_sr_img",
data["img_type"] = "jpg"
files={"file": image}


https://www.npmjs.com/package/reddit-api-image-upload
2 changes: 1 addition & 1 deletion docs/Twitter.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ keys will not be needed anymore.
- set up User authentication settings
- read and write
- fairpost is a bot
- redirect url with host/port from your .env (http://localhost:8000)
- redirect url with host/port from your .env (http://localhost:8000/callback)
- website https://github.com/commonpike/fairpost
- From the Oauth 01 settings
- generate Api Key and secret
Expand Down
40 changes: 40 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"license": "ISC",
"dependencies": {
"dotenv": "^16.0.3",
"fast-xml-parser": "^4.3.2",
"log4js": "^6.9.1",
"node-fetch": "^2.6.7",
"sharp": "0.31.1",
Expand Down
12 changes: 6 additions & 6 deletions public/auth/return.html → public/auth/callback.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@
</style>
</head>
<body>
<svg width="64px" height="64px" viewBox="0 0 769 773" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>fairpost-icon</title>
<svg width="64px" height="64px" viewBox="0 0 768 768" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>fairpost-icon copy</title>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="fairpost-icon" transform="translate(0.000000, -0.000000)" fill="#000000" fill-rule="nonzero">
<g id="check-box-3" transform="translate(0.000000, 4.000000)">
<g id="fairpost-icon-copy" fill="#000000" fill-rule="nonzero">
<g id="check-box-3">
<path d="M640,0 L128,0 C57.6,0 0,57.6 0,128 L0,640 C0,710.4 57.6,768 128,768 L640,768 C710.4,768 768,710.4 768,640 L768,128 C768,57.6 710.4,0 640,0 Z M704,640 C704,675.2 675.2,704 640,704 L128,704 C92.8,704 64,675.2 64,640 L64,128 C64,92.8 92.8,64 128,64 L640,64 C675.2,64 704,92.8 704,128 L704,640 Z" id="Shape"></path>
</g>
<g id="ios-send" transform="translate(0.000000, 57.000000)">
<path d="M692.464598,1.60131787 L8.87178864,299.577735 C-3.23214289,305.351028 -2.85971422,322.670907 9.43043163,328.07173 L194.341262,432.549711 C205.327908,438.695474 218.921554,437.391828 228.418485,429.197476 L593.026145,114.832356 C595.446932,112.783768 601.219576,108.872828 603.454148,111.107651 C605.874934,113.528709 602.150648,119.115767 600.10229,121.536826 L284.655213,476.873703 C275.903139,486.744172 274.599639,501.270522 281.675784,512.444638 L402.528885,706.315544 C408.487743,718.048365 425.433247,717.86213 430.833463,705.943073 L713.506818,22.2734318 C719.651891,8.86449303 705.685816,-4.73068099 692.464598,1.60131787 Z" id="Path"></path>
<g id="ios-send" transform="translate(0.000000, 53.000000)">
<path d="M692.464598,1.60131787 L8.87178864,299.577735 C-3.23214289,305.351028 -2.85971422,322.670907 9.43043163,328.07173 L160.186375,475.300377 C171.173021,481.44614 184.766667,480.142494 194.263598,471.948142 L593.026145,114.832356 C595.446932,112.783768 601.219576,108.872828 603.454148,111.107651 C605.874934,113.528709 602.150648,119.115767 600.10229,121.536826 L250.500326,519.624369 C241.748252,529.494838 240.444752,544.021188 247.520897,555.195304 L402.528885,706.315544 C408.487743,718.048365 425.433247,717.86213 430.833463,705.943073 L713.506818,22.2734318 C719.651891,8.86449303 705.685816,-4.73068099 692.464598,1.60131787 Z" id="Path"></path>
</g>
</g>
</g>
Expand Down
12 changes: 6 additions & 6 deletions public/auth/index.html → public/auth/request.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@
</style>
</head>
<body>
<svg width="64px" height="64px" viewBox="0 0 769 773" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>fairpost-icon</title>
<svg width="64px" height="64px" viewBox="0 0 768 768" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>fairpost-icon copy</title>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="fairpost-icon" transform="translate(0.000000, -0.000000)" fill="#000000" fill-rule="nonzero">
<g id="check-box-3" transform="translate(0.000000, 4.000000)">
<g id="fairpost-icon-copy" fill="#000000" fill-rule="nonzero">
<g id="check-box-3">
<path d="M640,0 L128,0 C57.6,0 0,57.6 0,128 L0,640 C0,710.4 57.6,768 128,768 L640,768 C710.4,768 768,710.4 768,640 L768,128 C768,57.6 710.4,0 640,0 Z M704,640 C704,675.2 675.2,704 640,704 L128,704 C92.8,704 64,675.2 64,640 L64,128 C64,92.8 92.8,64 128,64 L640,64 C675.2,64 704,92.8 704,128 L704,640 Z" id="Shape"></path>
</g>
<g id="ios-send" transform="translate(0.000000, 57.000000)">
<path d="M692.464598,1.60131787 L8.87178864,299.577735 C-3.23214289,305.351028 -2.85971422,322.670907 9.43043163,328.07173 L194.341262,432.549711 C205.327908,438.695474 218.921554,437.391828 228.418485,429.197476 L593.026145,114.832356 C595.446932,112.783768 601.219576,108.872828 603.454148,111.107651 C605.874934,113.528709 602.150648,119.115767 600.10229,121.536826 L284.655213,476.873703 C275.903139,486.744172 274.599639,501.270522 281.675784,512.444638 L402.528885,706.315544 C408.487743,718.048365 425.433247,717.86213 430.833463,705.943073 L713.506818,22.2734318 C719.651891,8.86449303 705.685816,-4.73068099 692.464598,1.60131787 Z" id="Path"></path>
<g id="ios-send" transform="translate(0.000000, 53.000000)">
<path d="M692.464598,1.60131787 L8.87178864,299.577735 C-3.23214289,305.351028 -2.85971422,322.670907 9.43043163,328.07173 L160.186375,475.300377 C171.173021,481.44614 184.766667,480.142494 194.263598,471.948142 L593.026145,114.832356 C595.446932,112.783768 601.219576,108.872828 603.454148,111.107651 C605.874934,113.528709 602.150648,119.115767 600.10229,121.536826 L250.500326,519.624369 C241.748252,529.494838 240.444752,544.021188 247.520897,555.195304 L402.528885,706.315544 C408.487743,718.048365 425.433247,717.86213 430.833463,705.943073 L713.506818,22.2734318 C719.651891,8.86449303 705.685816,-4.73068099 692.464598,1.60131787 Z" id="Path"></path>
</g>
</g>
</g>
Expand Down
4 changes: 2 additions & 2 deletions src/auth/FacebookAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default class FacebookAuth extends OAuth2Client {
url.pathname = this.GRAPH_API_VERSION + "/dialog/oauth";
const query = {
client_id: clientId,
redirect_uri: this.getRedirectUri(),
redirect_uri: this.getCallbackUrl(),
state: state,
response_type: "code",
scope: [
Expand Down Expand Up @@ -72,7 +72,7 @@ export default class FacebookAuth extends OAuth2Client {
clientId: string,
clientSecret: string,
): Promise<string> {
const redirectUri = this.getRedirectUri();
const redirectUri = this.getCallbackUrl();

const result = await this.get("oauth/access_token", {
client_id: clientId,
Expand Down
2 changes: 1 addition & 1 deletion src/auth/InstagramAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export default class InstagramAuth extends FacebookAuth {
url.pathname = this.GRAPH_API_VERSION + "/dialog/oauth";
const query = {
client_id: clientId,
redirect_uri: this.getRedirectUri(),
redirect_uri: this.getCallbackUrl(),
state: state,
response_type: "code",
scope: [
Expand Down
22 changes: 11 additions & 11 deletions src/auth/OAuth2Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ class DeferredResponseQuery {
* requesting remote permissions on a service
*/
export default class OAuth2Client {
protected getClientUrl(): string {
const clientHost = Storage.get("settings", "CLIENT_HOSTNAME");
const clientPort = Number(Storage.get("settings", "CLIENT_PORT"));
protected getRequestUrl(): string {
const clientHost = Storage.get("settings", "REQUEST_HOSTNAME");
const clientPort = Number(Storage.get("settings", "REQUEST_PORT"));
return `http://${clientHost}:${clientPort}`;
}

protected getRedirectUri(): string {
return this.getClientUrl() + "/return";
protected getCallbackUrl(): string {
return this.getRequestUrl() + "/callback";
}

/**
Expand All @@ -48,25 +48,25 @@ export default class OAuth2Client {
serviceName: string,
serviceLink: string,
): Promise<{ [key: string]: string | string[] }> {
const clientHost = Storage.get("settings", "CLIENT_HOSTNAME");
const clientPort = Number(Storage.get("settings", "CLIENT_PORT"));
const clientHost = Storage.get("settings", "REQUEST_HOSTNAME");
const clientPort = Number(Storage.get("settings", "REQUEST_PORT"));
const server = http.createServer();
const deferred = new DeferredResponseQuery();

server.listen(clientPort, clientHost, () => {
console.log(`Open a web browser and go to ${this.getClientUrl()}`);
console.log(`Open a web browser and go to ${this.getRequestUrl()}`);
});
const requestListener = async function (
request: http.IncomingMessage,
response: http.ServerResponse,
) {
const parsed = url.parse(request.url ?? "/", true);
if (parsed.pathname === "/return") {
if (parsed.pathname === "/callback") {
let result = "";
for (const key in parsed.query) {
result += key + " : " + String(parsed.query[key]) + "\n";
}
let body = fs.readFileSync("public/auth/return.html", "utf8");
let body = fs.readFileSync("public/auth/callback.html", "utf8");
body = body.replace(/{{serviceName}}/g, serviceName);
body = body.replace(/{{result}}/g, result ?? "UNKNOWN");
response.setHeader("Content-Type", "text/html");
Expand All @@ -76,7 +76,7 @@ export default class OAuth2Client {
server.close();
deferred.resolve(parsed.query);
} else {
let body = fs.readFileSync("public/auth/index.html", "utf8");
let body = fs.readFileSync("public/auth/request.html", "utf8");
body = body.replace(/{{serviceLink}}/g, serviceLink);
body = body.replace(/{{serviceName}}/g, serviceName);
response.setHeader("Content-Type", "text/html");
Expand Down
Loading