Initial commit

This commit is contained in:
dangered wolf 2022-07-13 15:09:57 -04:00
commit 6094c9df98
No known key found for this signature in database
GPG key ID: 41E4D37680ED8B58
20 changed files with 4875 additions and 0 deletions

2
.gitattributes vendored Normal file
View file

@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=LF

20
.github/workflows/webpack.yml vendored Normal file
View file

@ -0,0 +1,20 @@
name: Webpack
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '16'
cache: 'npm'
cache-dependency-path: package-lock.json
- run: npm install
- run: npx webpack

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
dist
node_modules
wrangler.toml

2
.prettierignore Normal file
View file

@ -0,0 +1,2 @@
node_modules
dist

8
.prettierrc Normal file
View file

@ -0,0 +1,8 @@
{
"singleQuote": true,
"semi": true,
"trailingComma": "es5",
"tabWidth": 2,
"printWidth": 90,
"arrowParens": "avoid"
}

21
LICENSE.md Normal file
View file

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2022 dangered wolf
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.

43
README.md Normal file
View file

@ -0,0 +1,43 @@
# Pronouns
[![Webpack](https://github.com/dangeredwolf/pronouns-bot/actions/workflows/webpack.yml/badge.svg)](https://github.com/dangeredwolf/pronouns-bot/actions/workflows/webpack.yml)
### A next-gen Discord bot for managing pronouns, written for Cloudflare Workers for free and low-cost hosting, world-class reliability, infinite scalability, and fast response times around the world.
![The finished prompt](https://cdn.discordapp.com/attachments/165560751363325952/988283919738736650/2022-06-19T232721.978_chrome.png)
It is built for Discord interactions, like slash commands and message components, from the very beginning, so they have an experience that feels like a native part of Discord.
### [Check out the docs of how to use it](https://wlf.is/pronouns)
### [Invite to your server](https://wlf.is/pronouns/invite)
---
This bot began with [cloudflare/worker-typescript-template](https://github.com/cloudflare/worker-typescript-template) as a template, and also took inspiration from [advaith1/activities](https://github.com/advaith1/activities) and [discord/cloudflare-sample-app](https://github.com/discord/cloudflare-sample-app) to figure out how to best set-up and use Discord Interaction APIs.
# Quick Start
Pronouns is a decent bot to use as a basis for your own Cloudflare Workers Discord bot as it contains pretty much everything you'd need from an HTTP router to a command router to per-guild storage management.
Things you need
- A Cloudflare account, set up with Workers
- A Cloudflare Workers KV store (We use the name PRONOUNS_BOT_GUILD_SETTINGS)
- A Discord bot created at https://discord.com/developers
This bot uses [wrangler](https://github.com/cloudflare/wrangler), so you should familiarize yourself with it to learn how to deploy your bot.
Check out [discord/cloudflare-sample-app](https://github.com/discord/cloudflare-sample-app) to learn how to set up your Discord bot for interactions. You'll need to set up your worker to configure interactions.
You'll want to configure the following secrets using wrangler:
`DISCORD_PUBLIC_KEY`
`DISCORD_APPLICATION_ID`
`PRONOUNS_BOT_TOKEN`
`PRONOUNS_BOT_TEST_GUILD_ID`
To register commands, you can enable the `/__register` HTTP endpoint in `src/server.ts` to register your commands initially. It's suggested you disable this endpoint afterward though to prevent third parties from trying to re-run command registration. Once this is done once, you can register commands globally or for your test guild using the `/register_guild` and `/register_global` commands in your test server (specified in `PRONOUNS_BOT_TEST_GUILD_ID`).

4566
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

30
package.json Normal file
View file

@ -0,0 +1,30 @@
{
"name": "pxtwitter",
"version": "1.0.0",
"description": "Cloudflare worker TypeScript template",
"main": "dist/worker.js",
"scripts": {
"build": "webpack",
"publish": "wrangler publish",
"log": "wrangler tail",
"reload": "wrangler publish && wrangler tail",
"register": "node src/register.js",
"prettier": "prettier --write ."
},
"author": "dangered wolf",
"license": "MIT",
"devDependencies": {
"@cloudflare/workers-types": "^3.13.0",
"@types/service-worker-mock": "^2.0.1",
"prettier": "^2.7.1",
"service-worker-mock": "^2.0.5",
"ts-loader": "^9.3.1",
"typescript": "^4.7.4",
"webpack": "^5.73.0",
"webpack-cli": "^4.10.0",
"wrangler": "^2.0.15"
},
"dependencies": {
"itty-router": "^2.6.1"
}
}

4
renovate.json Normal file
View file

@ -0,0 +1,4 @@
{
"extends": ["config:base"],
"rangeStrategy": "bump"
}

25
src/constants.ts Normal file
View file

@ -0,0 +1,25 @@
const fakeChromeVersion = '103';
export const Constants = {
REDIRECT_URL: 'https://github.com/dangeredwolf',
TWITTER_ROOT: 'https://twitter.com',
GUEST_BEARER_TOKEN: `Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA`,
BASE_HEADERS: {
'sec-ch-ua': `".Not/A)Brand";v="99", "Google Chrome";v="${fakeChromeVersion}", "Chromium";v="${fakeChromeVersion}"`,
DNT: `1`,
'x-twitter-client-language': `en`,
'sec-ch-ua-mobile': `?0`,
'content-type': `application/x-www-form-urlencoded`,
'User-Agent': `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${fakeChromeVersion}.0.0.0 Safari/537.36`,
'x-twitter-active-user': `yes`,
'sec-ch-ua-platform': `"Windows"`,
Accept: `*/*`,
Origin: `https://twitter.com`,
'Sec-Fetch-Site': `same-site`,
'Sec-Fetch-Mode': `cors`,
'Sec-Fetch-Dest': `empty`,
Referer: `https://twitter.com/`,
'Accept-Encoding': `gzip, deflate, br`,
'Accept-Language': `en`,
},
};

19
src/drivers/guest.ts Normal file
View file

@ -0,0 +1,19 @@
import { Constants } from '../constants';
export const fetchUsingGuest = async (
screenName: string,
status: string
): Promise<any> => {
const activate = await fetch(`${Constants.TWITTER_ROOT}/1.1/guest/activate.json`, {
method: 'POST',
headers: {
...Constants.BASE_HEADERS,
Authorization: `Bearer ${Constants.GUEST_BEARER_TOKEN}`,
},
body: '',
});
console.log(activate.json());
return activate.json();
};

3
src/global.d.ts vendored Normal file
View file

@ -0,0 +1,3 @@
declare const TWITTER_BEARER_TOKEN: string;
declare const TWITTER_API_KEY: string;
declare const TWITTER_API_KEY_SECRET: string;

11
src/html.ts Normal file
View file

@ -0,0 +1,11 @@
import { Strings } from './strings';
export const Html = {
BASE_HTML: `<!DOCTYPE html>
<!-- 👋 Hello robots and hackers -->
<html {lang}>
<head>
{headers}
</head>
`,
};

40
src/server.ts Normal file
View file

@ -0,0 +1,40 @@
import { Router } from 'itty-router';
import { Constants } from './constants';
import { fetchUsingGuest } from './drivers/guest';
/*
Useful little function to format strings for us
*/
declare global {
interface String {
format(options: any): string;
}
}
String.prototype.format = function (options: any) {
return this.replace(/{([^{}]+)}/g, (match: string, name: string) => {
if (options[name] !== undefined) {
return options[name];
}
return match;
});
};
const router = Router();
router.get('/:handle/status/:id', async (request: any) => {
const { handle, id } = request.params;
return new Response(await fetchUsingGuest(handle, id), { status: 200 });
});
router.all('*', async request => {
return Response.redirect(Constants.REDIRECT_URL);
});
/*
Event to receive web requests on Cloudflare Worker
*/
addEventListener('fetch', (event: FetchEvent) => {
event.respondWith(router.handle(event.request));
});

1
src/status.ts Normal file
View file

@ -0,0 +1 @@
export const handleStatus = (screenName: string, status: number) => {};

20
src/strings.ts Normal file
View file

@ -0,0 +1,20 @@
declare global {
interface String {
format(options: any): string;
}
}
/*
Useful little function to format strings for us
*/
String.prototype.format = function (options: any) {
return this.replace(/{([^{}]+)}/g, (match: string, name: string) => {
if (options[name] !== undefined) {
return options[name];
}
return match;
});
};
export const Strings = {};

18
tsconfig.json Normal file
View file

@ -0,0 +1,18 @@
{
"compilerOptions": {
"outDir": "./dist",
"module": "commonjs",
"target": "es2022",
"lib": ["es2022"],
"alwaysStrict": true,
"strict": true,
"preserveConstEnums": true,
"moduleResolution": "node",
"allowJs": true,
"sourceMap": true,
"esModuleInterop": true,
"types": ["@cloudflare/workers-types", "@types/service-worker-mock"]
},
"include": ["src"],
"exclude": ["node_modules", "dist", "test"]
}

31
webpack.config.js Normal file
View file

@ -0,0 +1,31 @@
const path = require('path');
module.exports = {
entry: {
worker: './src/server.ts',
},
output: {
filename: '[name].js',
path: path.join(__dirname, 'dist'),
},
mode: 'production',
resolve: {
extensions: ['.ts', '.tsx', '.js'],
fallback: { util: false },
},
plugins: [],
optimization: {
mangleExports: 'size',
},
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'ts-loader',
options: {
transpileOnly: true,
},
},
],
},
};

8
wrangler.example.toml Normal file
View file

@ -0,0 +1,8 @@
name = "pxtwitter"
account_id = "[CLOUDFLARE_ACCOUNT_ID]"
workers_dev = true
main = "./dist/worker.js"
compatibility_date = "2022-07-13"
[build]
command = "npm run build"