Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/npm_and_yarn/mongodb-4.17.0
Browse files Browse the repository at this point in the history
  • Loading branch information
sdip15fa authored Apr 24, 2024
2 parents 7a1e1d0 + da9630f commit 37184c7
Show file tree
Hide file tree
Showing 93 changed files with 4,627 additions and 707 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/publish-docker.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Publish Docker Image 'jeeetpaul/whatsbot'
name: Publish Docker Image 'wcyat/whatsbot'

on:
push:
Expand All @@ -20,5 +20,5 @@ jobs:
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
repository: jeeetpaul/whatsbot
repository: wcyat/whatsbot
tag_with_ref: true
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ session-output/*
session-output
session.secure
/.lh/
**/*.js
/dist/
/docker/data
/docker/wtstodis-data
2 changes: 1 addition & 1 deletion .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ update-dependencies:
- git reset --hard origin/main
script:
- yarn
- yarn add whatsapp-web.js@latest
- yarn add https://github.com/pedroslopez/whatsapp-web.js
- git commit -a -m "Update whatsapp-web.js" || exit 0
- git push origin main
rules:
Expand Down
12 changes: 5 additions & 7 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,19 @@ COPY . ./

RUN yarn build

RUN yarn install --production

FROM ghcr.io/puppeteer/puppeteer:latest

USER root

WORKDIR /app

RUN apt-get update && apt-get install -y ffmpeg && rm -rf /var/lib/{apt,dpkg,cache,log}/
USER root

COPY --from=build /app/dist ./
COPY ./yarn.lock ./yarn.lock
RUN apt-get update && apt-get install -y ffmpeg stockfish && rm -rf /var/lib/{apt,dpkg,cache,log}/

COPY ./package.json ./yarn.lock ./
RUN yarn install --production

COPY --from=build /app/dist ./

VOLUME ["/app/data"]

CMD ["node", "startProcess.js"]
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Whatsapp to Discord
# Whatsbot

Forward messages between whatsapp and discord. Based on [WhatsBot](https://github.com/tuhinpal/WhatsBot/).
This is a feature-rich heavily-modified Whatsbot fork.

<!-- <h1 align="center">
<a href="https://github.com/tuhinpal/WhatsBot"><img src="https://telegra.ph/file/96ccad5945c18944c5f15.png" alt="whatsbot" width="290"></a>
Expand Down
13 changes: 13 additions & 0 deletions cf-worker/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# http://editorconfig.org
root = true

[*]
indent_style = tab
tab_width = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.yml]
indent_style = space
6 changes: 6 additions & 0 deletions cf-worker/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"printWidth": 140,
"singleQuote": true,
"semi": true,
"useTabs": true
}
17 changes: 17 additions & 0 deletions cf-worker/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "whatsbot-worker",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"deploy": "wrangler deploy",
"dev": "wrangler dev",
"start": "wrangler dev"
},
"devDependencies": {
"wrangler": "^3.0.0"
},
"dependencies": {
"@cloudflare/ai": "^1.1.0"
}
}
45 changes: 45 additions & 0 deletions cf-worker/src/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { BadRequestException, UnauthorizedException } from './exceptions.js';
import { Env } from './types.js';

export function basicAuthentication(request: Request) {
const Authorization = request.headers.get('Authorization');

const [scheme, encoded] = Authorization?.split(' ') || ['', ''];

// The Authorization header must start with Basic, followed by a space.
if (!encoded || scheme !== 'Basic') {
throw new BadRequestException('Malformed authorization header.');
}

// Decodes the base64 value and performs unicode normalization.
// @see https://datatracker.ietf.org/doc/html/rfc7613#section-3.3.2 (and #section-4.2.2)
// @see https://dev.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/normalize
const buffer = Uint8Array.from(atob(encoded), (character) => character.charCodeAt(0));
const decoded = new TextDecoder().decode(buffer).normalize();

// The username & password are split by the first colon.
//=> example: "username:password"
const index = decoded.indexOf(':');

// The user & password are split by the first colon and MUST NOT contain control characters.
// @see https://tools.ietf.org/html/rfc5234#appendix-B.1 (=> "CTL = %x00-1F / %x7F")
// eslint-disable-next-line no-control-regex
if (index === -1 || /[\0-\x1F\x7F]/.test(decoded)) {
throw new BadRequestException('Invalid authorization value.');
}

return {
user: decoded.substring(0, index),
pass: decoded.substring(index + 1),
};
}

export function verifyCredentials(user: string, pass: string, env: Env) {
if (env.AUTH_USER !== user) {
throw new UnauthorizedException('Invalid credentials.');
}

if (env.AUTH_PASSWORD !== pass) {
throw new UnauthorizedException('Invalid credentials.');
}
}
35 changes: 35 additions & 0 deletions cf-worker/src/exceptions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
export class UnauthorizedException {
status: number;
statusText: string;
reason: string;

constructor(reason: string) {
this.status = 401;
this.statusText = 'Unauthorized';
this.reason = reason;
}
}

export class BadRequestException {
status: number;
statusText: string;
reason: string;

constructor(reason: string) {
this.status = 400;
this.statusText = 'Bad Request';
this.reason = reason;
}
}

export class FailedException {
status: number;
statusText: string;
reason: string;

constructor(reason: string) {
this.status = 500;
this.statusText = 'Internal Server Error';
this.reason = reason;
}
}
133 changes: 133 additions & 0 deletions cf-worker/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import { Ai } from '@cloudflare/ai';
import { Env } from './types.js';
import { BadRequestException, FailedException } from './exceptions.js';
import { basicAuthentication, verifyCredentials } from './auth.js';

export default {
async fetch(request: Request, env: Env) {
const { protocol } = new URL(request.url);

// In the case of a Basic authentication, the exchange MUST happen over an HTTPS (TLS) connection to be secure.
if ('https:' !== protocol || 'https' !== request.headers.get('x-forwarded-proto')) {
throw new BadRequestException('Please use a HTTPS connection.');
}

if (request.headers.has('Authorization')) {
// Throws exception when authorization fails.
const { user, pass } = basicAuthentication(request);
try {
verifyCredentials(user, pass, env);
} catch {
// Not authenticated.
return new Response('You need to login.', {
status: 401,
headers: {
// Prompts the user for credentials.
'WWW-Authenticate': 'Basic realm="my scope", charset="UTF-8"',
},
});
}

// Only returns this response when no exception is thrown.
} else {
// Not authenticated.
return new Response('You need to login.', {
status: 401,
headers: {
// Prompts the user for credentials.
'WWW-Authenticate': 'Basic realm="my scope", charset="UTF-8"',
},
});
}

const ai = new Ai(env.AI);

const url = new URL(request.url);
const params = url.searchParams;
const path = url.pathname;

if ((path === '/' && request.method === 'GET') || path === '/llama') {
const prompt = params.get('prompt');
let messages: { role: 'user' | 'system' | 'assistant'; content: string }[] = [];
try {
messages = JSON.parse(decodeURIComponent(params.get('messages')) || '[]');
} catch {
return new BadRequestException('Messages must be a valid JSON array.');
}

const chat = {
messages: [
{
role: 'system',
content: 'Below is an instruction that describes a task. Write a response that appropriately completes the request.',
},
...(messages?.length
? messages
: [
{
role: 'user',
content: prompt,
},
]),
],
};
let response: string;
for (let i = 5; i > 0; i--) {
try {
response = await ai.run('@cf/meta/llama-3-8b-instruct', chat);
break;
} catch {
if (i === 1) {
return new FailedException('Failed to generate after five tries.');
}
}
}

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return Response.json(response);
}

if ((path === '/' && request.method === 'POST') || path === '/transcribe') {
const contentType = request.headers.get('Content-Type');
if (!contentType || !contentType.includes('multipart/form-data')) {
return new Response('Content-Type must be "multipart/form-data"', { status: 400 });
}

const formData = await request.formData();
const audioFile = formData.get('audio');

// Check if audio file exists in the POST request
if (!audioFile || !(audioFile instanceof File)) {
return new Response('Audio file not found in the request', { status: 400 });
}

// Convert audio file to ArrayBuffer
const blob = await audioFile.arrayBuffer();
const inputs = {
audio: [...new Uint8Array(blob)],
};
const response = await ai.run('@cf/openai/whisper', inputs);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return Response.json(response);
}

if (path === '/sd') {
const prompt = params.get('prompt');
const inputs = {
prompt,
};

const response = await ai.run('@cf/lykon/dreamshaper-8-lcm', inputs);

return new Response(response, {
headers: {
'content-type': 'image/png',
},
});
}
},
};
5 changes: 5 additions & 0 deletions cf-worker/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface Env {
AUTH_USER: string;
AUTH_PASSWORD: string;
AI: string;
}
7 changes: 7 additions & 0 deletions cf-worker/wrangler.toml.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
name = "your-worker-name"
main = "src/index.ts"
compatibility_date = "2023-10-07"
workers_dev = true

[ai]
binding = "AI"
Loading

0 comments on commit 37184c7

Please sign in to comment.