Skip to content

Commit

Permalink
Merge pull request #23 from fabriguespe/updates_v3
Browse files Browse the repository at this point in the history
Updates docs
  • Loading branch information
fabriguespe authored Jun 9, 2024
2 parents 9a3314f + 3d6317e commit 7d3d2d2
Show file tree
Hide file tree
Showing 12 changed files with 116 additions and 66 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ See more examples in the [Awesome XMTP ⭐️](https:/xmtp/awesome-x
> **Note**
> Before starting the bots locally, install the necessary dependencies by running `yarn` first. Update yarn with `yarn set version stable`
- `yarn start:conversational`: Start the conversational bot
- `yarn start:gm`: Start the GM bot
- `yarn start:conversational`: Start the conversational bot
- `yarn start:group`: Start the Group bot

## Contributing
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,57 +3,67 @@ import { users } from "../lib/users.js";

export async function handler(context: HandlerContext) {
const { senderAddress, content, typeId } = context.message;
const { params, users: receivers, url } = content;

const { params } = content;
let amount: number = 0,
receiverAddresses: string[] = [],
reference: string = "";

// Handle different types of messages
if (typeId === "reply") {
// Replies with degen // [!code hl] // [!code focus]
const { content: reply, receiver } = content;
//Reply
// Process reply messages
receiverAddresses = [receiver];
if (reply.includes("$degen")) {
const match = reply.match(/(\d+)/);
if (match) amount = parseInt(match[0]);
if (match) amount = parseInt(match[0]); // Extract amount from reply
}
} else if (typeId === "text") {
// Uses tip command // [!code hl] // [!code focus]
const { content: text } = content;
// Process text commands starting with "/tip"
if (text.startsWith("/tip")) {
const { amount: extractedAmount, username } = params;

amount = parseInt(extractedAmount) || 10;
receiverAddresses = receivers;
amount = extractedAmount || 10; // Default amount if not specified
receiverAddresses = username; // Extract receiver from parameters
}
} else if (typeId === "reaction") {
// Uses reaction emoji to tip // [!code hl] // [!code focus]
const { content: reaction, action, receiver } = content;

// Process reactions, specifically "degen" added reactions
if (reaction === "degen" && action === "added") {
amount = 10;
amount = 10; // Set a fixed amount for reactions
receiverAddresses = [receiver];
}
}
// Find sender user details
const sender = users.find((user: any) => user.address === senderAddress);

// Validate transaction feasibility
if (!sender || receiverAddresses.length === 0 || amount === 0) {
context.reply("Sender or receiver or amount not found.");
return;
}

// Check if sender has enough DEGEN tokens
if (sender.degen >= amount * receiverAddresses.length) {
// Process sending DEGEN tokens to each receiver
receiverAddresses.forEach(async (receiver: any) => {
context.reply(
`You received ${amount} DEGEN tokens from ${sender.username}. Your new balance is ${receiver.degen} DEGEN tokens.`,
[receiver.address],
[receiver.address], // Notify only 1 address // [!code hl] // [!code focus]
);
});
// Notify sender of the transaction details
context.reply(
`You sent ${
amount * receiverAddresses.length
} DEGEN tokens in total. Your remaining balance: ${
sender.degen
sender.degen // The hypotetical logic of distributing tokens // [!code hl] // [!code focus]
} DEGEN tokens.`,
[sender.address],
[sender.address], // Notify only 1 address // [!code hl] // [!code focus]
reference,
);
} else {
Expand Down
30 changes: 15 additions & 15 deletions examples/group/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import "dotenv/config";
import { run, HandlerContext } from "@xmtp/botkit";
import { users } from "./lib/users.js";
import { handler as baseHandler } from "./bots/baseframe.js";
import { handler as baseHandler } from "./handler/frame.js";
import { commands } from "./commands.js";
import { handler as basebetHandler } from "./bots/basebet.js";
import { handler as tippingHandler } from "./bots/degen.js";
import { handler as gptHandler } from "./bots/gpt.js";
import { handler as gamesHandler } from "./bots/games.js";
import { handler as generalHandler } from "./bots/general.js";
import { handler as bet } from "./handler/bet.js";
import { handler as tipping } from "./handler/tipping.js";
import { handler as gpt } from "./handler/gpt.js";
import { handler as games } from "./handler/games.js";
import { handler as general } from "./handler/general.js";

const newBotConfig = {
context: {
Expand All @@ -21,29 +21,29 @@ run(async (context: HandlerContext) => {
populateFakeUsers(context);
if (typeId == "reaction") {
const { action, content: emoji } = content;
if (emoji == "degen" && action == "added") await tippingHandler(context);
if (emoji == "degen" && action == "added") await tipping(context);
} else if (typeId == "reply") {
const { receiver, content: reply } = content;
if (receiver && reply.includes("degen")) await tippingHandler(context);
if (receiver && reply.includes("degen")) await tipping(context);
} else if (typeId == "text") {
const { content: text } = content;
if (text.startsWith("@bot")) {
await gptHandler(context, commands);
if (text.startsWith("/tip")) {
await tipping(context);
} else if (text.startsWith("@bot")) {
await gpt(context, commands);
} else if (text.startsWith("/bet")) {
await basebetHandler(context);
await bet(context);
} else if (
text.startsWith("/send") ||
text.startsWith("/swap") ||
text.startsWith("/mint") ||
text.startsWith("/show")
) {
await baseHandler(context);
} else if (text.startsWith("/tip")) {
await tippingHandler(context);
} else if (text.startsWith("/game")) {
await gamesHandler(context);
await games(context);
} else if (text.startsWith("/")) {
await generalHandler(context);
await general(context);
}
}
}, newBotConfig);
Expand Down
1 change: 1 addition & 0 deletions packages/botkit/src/lib-mls/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export const runGroup = async (
const extractedValues = extractCommandValues(
content?.content,
commands,
[],
);
content = {
...content,
Expand Down
60 changes: 46 additions & 14 deletions packages/docs/docs/pages/examples/group/index.mdx
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
# Group Bot

This is a powerful group bot that will allow you to understand the potential.
This is a powerful group bot that will allow you to understand the potential and all of its features. Through many handlers you will be able to understand different use cases.

## Structure

> Check out the [repository](https:/xmtp-labs/botkit/tree/main/examples/group) for the full code.
```
bot-project/ # Your project's root directory.
bot-project/
├── src/
│ ├── index.ts # Simple group bot. // [!code hl] // [!code focus]
│ ├── index.ts # Index file of the bot. // [!code hl] // [!code focus]
│ ├── command.ts # For handling commands. // [!code hl] // [!code focus]
├── src/
│ ├──handler/
│ ├── command.ts # Handles the command logic. // [!code hl] // [!code focus]
│ ├── bet.ts # Handles the bet logic. // [!code hl] // [!code focus]
│ ├── tipping.ts # Handles the tipping logic. // [!code hl] // [!code focus]
│ ├── gpt.ts # Handles the gpt logic. // [!code hl] // [!code focus]
│ ├── games.ts # Handles the games logic. // [!code hl] // [!code focus]
│ ├── general.ts # Handles the general logic. // [!code hl] // [!code focus]
├── package.json
├── tsconfig.json
└── .env
Expand All @@ -20,28 +29,51 @@ bot-project/ # Your project's root directory.
```jsx [src/index.ts]
import "dotenv/config";
import { run, HandlerContext } from "@xmtp/botkit";
import { commands } from "./commands.ts";
import { users } from "./lib/users.js";
import { handler as baseHandler } from "./bots/frame.js";
import { commands } from "./commands.js";
import { handler as bet } from "./bots/bet.js";
import { handler as tipping } from "./bots/degen.js";
import { handler as gpt } from "./bots/gpt.js";
import { handler as games } from "./bots/games.js";
import { handler as general } from "./bots/general.js";

const newBotConfig = {
commands: commands,
context: {
commands: commands,
users: users,
},
};

// Main bot runner
run(async (context: HandlerContext) => {
const { content, typeId, senderAddress } = context.message;
const { content: text } = content;

if (typeId == "reaction") {
const { action, content: emoji, receiver } = content;
// handle reactions
const { action, content: emoji } = content;
if (emoji == "degen" && action == "added") await tipping(context);
} else if (typeId == "reply") {
const { content: reply, receiver } = content;
// handle replies
const { receiver, content: reply } = content;
if (receiver && reply.includes("degen")) await tipping(context);
} else if (typeId == "text" && text.startsWith("/tip")) {
await tipping(context);
} else if (typeId == "text") {
const { content: text, receiver } = content;
const { content: text } = content;
if (text.startsWith("@bot")) {
// Handle direct messages to the bot
}else if (text.startsWith("/help")) {
// Handle help command
await gptHandler(context, commands);
} else if (text.startsWith("/bet")) {
await betHandler(context);
} else if (
text.startsWith("/send") ||
text.startsWith("/swap") ||
text.startsWith("/mint") ||
text.startsWith("/show")
) {
await baseHandler(context);
} else if (text.startsWith("/game")) {
await games(context);
} else if (text.startsWith("/")) {
await general(context);
}
}
}, newBotConfig);
Expand Down
59 changes: 33 additions & 26 deletions packages/docs/docs/pages/examples/group/tipping.mdx
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
# Tipping

```jsx
In this example you can tip using 3 primitives:

- Emoji reaction `emoji:🎩`
- Text message starting with `/tip @bob 10 degen`
- Reply `10 $degen`

```tsx [handler/tipping.ts]
import { HandlerContext } from "@xmtp/botkit";
import { mapUsernamesToAddresses } from "@xmtp/botkit";
import { users } from "../lib/users.js";

export async function handler(context: HandlerContext) {
Expand All @@ -12,64 +17,66 @@ export async function handler(context: HandlerContext) {
receiverAddresses: string[] = [],
reference: string = "";

// Handle different types of messages
if (typeId === "reply") {
// Replies with degen // [!code hl] // [!code focus]
const { content: reply, receiver } = content;
//Reply
// Process reply messages
receiverAddresses = [receiver];
if (reply.includes("$degen")) {
const match = reply.match(/(\d+)/);
if (match) amount = parseInt(match[0]);
if (match) amount = parseInt(match[0]); // Extract amount from reply
}
} else if (typeId === "text") {
// Uses tip command // [!code hl] // [!code focus]
const { content: text } = content;
// Process text commands starting with "/tip"
if (text.startsWith("/tip")) {
const { amount: extractedAmount, username } = params;

//@ts-ignore
amount = parseInt(extractedAmount) || 10;
//@ts-ignore
receiverAddresses = mapUsernamesToAddresses(username, users);
amount = extractedAmount || 10; // Default amount if not specified
receiverAddresses = username; // Extract receiver from parameters
}
} else if (typeId === "reaction") {
// Uses reaction emoji to tip // [!code hl] // [!code focus]
const { content: reaction, action, receiver } = content;
//Reaction

// Process reactions, specifically "degen" added reactions
if (reaction === "degen" && action === "added") {
amount = 10;
amount = 10; // Set a fixed amount for reactions
receiverAddresses = [receiver];
}
}
const sender = users.find((user) => user.address === senderAddress);
const receivers = users.filter((user) =>
receiverAddresses.includes(user.address),
);
// Find sender user details
const sender = users.find((user: any) => user.address === senderAddress);

if (!sender || receivers.length === 0 || amount === 0) {
// Validate transaction feasibility
if (!sender || receiverAddresses.length === 0 || amount === 0) {
context.reply("Sender or receiver or amount not found.");
return;
}
if (sender.degen >= amount * receivers.length) {
sender.degen -= amount * receivers.length;
receivers.forEach(async (receiver) => {
receiver.degen += amount;

// Check if sender has enough DEGEN tokens
if (sender.degen >= amount * receiverAddresses.length) {
// Process sending DEGEN tokens to each receiver
receiverAddresses.forEach(async (receiver: any) => {
context.reply(
`You received ${amount} DEGEN tokens from ${sender.username}. Your new balance is ${receiver.degen} DEGEN tokens.`,
[receiver.address],
[receiver.address], // Notify only 1 address // [!code hl] // [!code focus]
);
//notifyUser(receiver, amount, sender);
});
// Notify sender of the transaction details
context.reply(
`You sent ${
amount * receivers.length
amount * receiverAddresses.length
} DEGEN tokens in total. Your remaining balance: ${
sender.degen
sender.degen // The hypotetical logic of distributing tokens // [!code hl] // [!code focus]
} DEGEN tokens.`,
[sender.address],
[sender.address], // Notify only 1 address // [!code hl] // [!code focus]
reference,
);
} else {
context.reply("Insufficient DEGEN tokens to send.");
}
}


```

0 comments on commit 7d3d2d2

Please sign in to comment.