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: Support wildcard in TWITTER_TARGET_USERS 1883 #1884

Merged
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
21 changes: 21 additions & 0 deletions jest.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"testEnvironment": "node",
"extensionsToTreatAsEsm": [".ts"],
"transform": {
"^.+\\.tsx?$": [
"ts-jest",
{
"useESM": true,
"tsconfig": {
"module": "esnext",
"target": "esnext",
"moduleResolution": "bundler"
}
}
]
},
"moduleNameMapper": {
"^@elizaos/core$": "<rootDir>/packages/core/src/index.ts",
"^@elizaos/(.*)$": "<rootDir>/packages/$1/src/index.ts"
}
}
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@
"typescript": "5.6.3",
"vite": "5.4.11",
"vitest": "2.1.5",
"viem": "2.21.58"
"viem": "2.21.58",
"ts-jest": "^29.1.1",
"@types/jest": "^29.5.11",
"jest": "^29.7.0"
},
"pnpm": {
"overrides": {
Expand Down
67 changes: 67 additions & 0 deletions packages/client-twitter/src/__tests__/environment.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { twitterEnvSchema } from "../environment";

describe("Twitter Environment Configuration", () => {
describe("Username Validation", () => {
const validateUsername = (username: string) => {
return twitterEnvSchema.parse({
TWITTER_DRY_RUN: false,
TWITTER_USERNAME: "test_user",
TWITTER_PASSWORD: "password",
TWITTER_EMAIL: "[email protected]",
TWITTER_2FA_SECRET: "",
TWITTER_RETRY_LIMIT: 5,
TWITTER_POLL_INTERVAL: 120,
POST_INTERVAL_MIN: 90,
POST_INTERVAL_MAX: 180,
ENABLE_ACTION_PROCESSING: false,
ACTION_INTERVAL: 5,
POST_IMMEDIATELY: false,
TWITTER_TARGET_USERS: [username],
});
};

it("should allow valid traditional usernames", () => {
expect(() => validateUsername("normal_user")).not.toThrow();
expect(() => validateUsername("user123")).not.toThrow();
expect(() => validateUsername("a_1_b_2")).not.toThrow();
});

it("should allow usernames starting with digits", () => {
expect(() => validateUsername("123user")).not.toThrow();
expect(() => validateUsername("42_test")).not.toThrow();
expect(() => validateUsername("007james")).not.toThrow();
});

it("should allow wildcard", () => {
expect(() => validateUsername("*")).not.toThrow();
});

it("should reject invalid usernames", () => {
expect(() => validateUsername("")).toThrow();
expect(() => validateUsername("user@123")).toThrow();
expect(() => validateUsername("user-123")).toThrow();
expect(() => validateUsername("user.123")).toThrow();
expect(() => validateUsername("a".repeat(16))).toThrow();
});

it("should handle array of usernames", () => {
const config = {
TWITTER_DRY_RUN: false,
TWITTER_USERNAME: "test_user",
TWITTER_PASSWORD: "password",
TWITTER_EMAIL: "[email protected]",
TWITTER_2FA_SECRET: "",
TWITTER_RETRY_LIMIT: 5,
TWITTER_POLL_INTERVAL: 120,
POST_INTERVAL_MIN: 90,
POST_INTERVAL_MAX: 180,
ENABLE_ACTION_PROCESSING: false,
ACTION_INTERVAL: 5,
POST_IMMEDIATELY: false,
TWITTER_TARGET_USERS: ["normal_user", "123digit", "*"],
};

expect(() => twitterEnvSchema.parse(config)).not.toThrow();
});
});
});
16 changes: 11 additions & 5 deletions packages/client-twitter/src/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@ export const DEFAULT_MAX_TWEET_LENGTH = 280;

const twitterUsernameSchema = z
.string()
.min(1, "An X/Twitter Username must be at least 1 characters long")
.min(1, "An X/Twitter Username must be at least 1 character long")
.max(15, "An X/Twitter Username cannot exceed 15 characters")
.regex(
/^[A-Za-z0-9_]*$/,
"An X Username can only contain letters, numbers, and underscores"
);
.refine((username) => {
// Allow wildcard '*' as a special case
if (username === "*") return true;

// Twitter usernames can:
// - Start with digits now
// - Contain letters, numbers, underscores
// - Must not be empty
return /^[A-Za-z0-9_]+$/.test(username);
}, "An X Username can only contain letters, numbers, and underscores");

/**
* This schema defines all required/optional environment settings,
Expand Down
54 changes: 41 additions & 13 deletions pnpm-lock.yaml

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

40 changes: 35 additions & 5 deletions scripts/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,57 @@
REQUIRED_NODE_VERSION=22
CURRENT_NODE_VERSION=$(node -v | cut -d'.' -f1 | sed 's/v//')

if (( CURRENT_NODE_VERSION < REQUIRED_NODE_VERSION )); then
if ((CURRENT_NODE_VERSION < REQUIRED_NODE_VERSION)); then
echo "Error: Node.js version must be $REQUIRED_NODE_VERSION or higher. Current version is $CURRENT_NODE_VERSION."
exit 1
fi

# Navigate to the script's directory
cd "$(dirname "$0")"/..

# If specific test file provided, run just that
if [[ "$1" == *".ts" ]]; then
echo -e "\033[1mRunning specific test: $1\033[0m"
node --experimental-vm-modules $(which jest) "$1"
exit $?
fi

# If package name provided, run just that package
if [ ! -z "$1" ]; then
package="$1"
package_path="packages/$package"

if [ ! -d "$package_path" ]; then
echo -e "\033[1mPackage directory '$package' not found\033[0m"
exit 1
fi

echo -e "\033[1mTesting package: $package\033[0m"
# Use find to get all test files and pass them explicitly to jest
test_files=$(find "packages/$package/src" -name "*.test.ts" -type f)
if [ -z "$test_files" ]; then
echo "No test files found"
exit 1
fi
echo "Found test files:"
echo "$test_files"
node --experimental-vm-modules $(which jest) $test_files
exit $?
fi

# Check if the packages directory exists
if [ ! -d "packages" ]; then
echo "Error: 'packages' directory not found."
exit 1
fi

# Find all packages under the packages directory
PACKAGES=( $(find packages -mindepth 1 -maxdepth 1 -type d -exec basename {} \;) )
PACKAGES=($(find packages -mindepth 1 -maxdepth 1 -type d -exec basename {} \;))

# Test packages in specified order
for package in "${PACKAGES[@]}"; do
package_path="packages/$package"

if [ ! -d "$package_path" ]; then
echo -e "\033[1mPackage directory '$package' not found, skipping...\033[0m"
continue
Expand Down Expand Up @@ -57,7 +87,7 @@ for package in "${PACKAGES[@]}"; do
echo "No package.json found in $package, skipping..."
fi

cd - > /dev/null || exit
cd - >/dev/null || exit
done

echo -e "\033[1mTest process completed.😎\033[0m"
echo -e "\033[1mTest process completed.😎\033[0m"
14 changes: 10 additions & 4 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@
"moduleResolution": "node",
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
"forceConsistentCasingInFileNames": true,
"allowImportingTsExtensions": true,
"noEmit": true
},
"files": [],
"references": [
{ "path": "packages/core" },
{ "path": "packages/client-slack" }
{
"path": "packages/core"
},
{
"path": "packages/client-slack"
}
]
}
}
Loading