Skip to content

Commit

Permalink
Merge pull request #598 from valory-xyz/tanya/twitter-cookies
Browse files Browse the repository at this point in the history
feat: saves twitter cookies to envs
  • Loading branch information
Tanya-atatakai authored Dec 17, 2024
2 parents 74340ac + 9fbdff3 commit aad5d7f
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 25 deletions.
3 changes: 2 additions & 1 deletion electron/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,8 @@ const createMainWindow = async () => {

try {
await scraper.login(username, password, email);
return { success: true };
const cookies = await scraper.getCookies();
return { success: true, cookies };
} catch (error) {
console.error('Twitter login error:', error);
return { success: false, error: error.message };
Expand Down
22 changes: 14 additions & 8 deletions frontend/components/SetupPage/SetupYourAgent/SetupYourAgent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -132,18 +132,20 @@ const SetupYourAgentForm = ({ serviceTemplate }: SetupYourAgentFormProps) => {

// validate the twitter credentials
setSubmitButtonText('Validating Twitter credentials...');
const isTwitterCredentialsValid = electronApi?.validateTwitterLogin
? await validateTwitterCredentials(
values.xEmail,
values.xUsername,
values.xPassword,
electronApi.validateTwitterLogin,
)
: false;
const { isValid: isTwitterCredentialsValid, cookies } =
electronApi?.validateTwitterLogin
? await validateTwitterCredentials(
values.xEmail,
values.xUsername,
values.xPassword,
electronApi.validateTwitterLogin,
)
: { isValid: false };
setTwitterCredentialsValidationStatus(
isTwitterCredentialsValid ? 'valid' : 'invalid',
);
if (!isTwitterCredentialsValid) return;
if (!cookies) return;

// wait for agent setup to complete
setSubmitButtonText('Setting up agent...');
Expand All @@ -165,6 +167,10 @@ const SetupYourAgentForm = ({ serviceTemplate }: SetupYourAgentFormProps) => {
...serviceTemplate.env_variables.TWIKIT_PASSWORD,
value: values.xPassword,
},
TWIKIT_COOKIES: {
...serviceTemplate.env_variables.TWIKIT_COOKIES,
value: cookies,
},
GENAI_API_KEY: {
...serviceTemplate.env_variables.GENAI_API_KEY,
value: values.geminiApiKey,
Expand Down
28 changes: 19 additions & 9 deletions frontend/components/SetupPage/SetupYourAgent/validation.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ServiceTemplate } from '@/client';
import { StakingProgramId } from '@/enums/StakingProgram';
import { ServicesService } from '@/service/Services';
import { XCookie } from '@/types/Cookies';

/**
* Validate the Google Gemini API key
Expand All @@ -21,6 +22,14 @@ export const validateGeminiApiKey = async (apiKey: string) => {
}
};

const formatXCookies = (cookiesArray: XCookie[]) => {
const cookiesObject: Record<string, string> = {};
cookiesArray.forEach((cookie) => {
cookiesObject[cookie.key] = cookie.value;
});
return JSON.stringify(cookiesObject);
};

/**
* Validate the Twitter credentials
*/
Expand All @@ -36,25 +45,26 @@ export const validateTwitterCredentials = async (
email: string;
username: string;
password: string;
}) => Promise<{ success: boolean }>,
) => {
if (!email || !username || !password) return false;
}) => Promise<{ success: boolean; cookies?: XCookie[] }>,
): Promise<{ isValid: boolean; cookies?: string }> => {
if (!email || !username || !password) return { isValid: false };

try {
const isValidated = await validateTwitterLogin({
const result = await validateTwitterLogin({
username,
password,
email,
});
if (isValidated.success) {
return true;

if (result.success && result.cookies) {
return { isValid: true, cookies: formatXCookies(result.cookies) };
}

console.error('Error validating Twitter credentials:', isValidated);
return false;
console.error('Error validating Twitter credentials:', result);
return { isValid: false };
} catch (error) {
console.error('Unexpected error validating Twitter credentials:', error);
return false;
return { isValid: false };
}
};

Expand Down
8 changes: 7 additions & 1 deletion frontend/constants/serviceTemplates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ export const SERVICE_TEMPLATES: ServiceTemplate[] = [
provision_type: EnvProvisionType.COMPUTED,
},
CELO_LEDGER_RPC: {
name: 'Base ledger RPC',
name: 'Celo ledger RPC',
description: '',
value: '',
provision_type: EnvProvisionType.COMPUTED,
Expand All @@ -212,6 +212,12 @@ export const SERVICE_TEMPLATES: ServiceTemplate[] = [
value: '',
provision_type: EnvProvisionType.USER,
},
TWIKIT_COOKIES: {
name: 'Twitter cookies',
description: '',
value: '',
provision_type: EnvProvisionType.USER,
},
GENAI_API_KEY: {
name: 'Gemini api key',
description: '',
Expand Down
3 changes: 2 additions & 1 deletion frontend/context/ElectronApiProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { get } from 'lodash';
import { createContext, PropsWithChildren } from 'react';

import { XCookie } from '@/types/Cookies';
import { ElectronStore, ElectronTrayIconStatus } from '@/types/ElectronApi';

type ElectronApiContextProps = {
Expand Down Expand Up @@ -40,7 +41,7 @@ type ElectronApiContextProps = {
username: string;
password: string;
email: string;
}) => Promise<{ success: boolean }>;
}) => Promise<{ success: boolean; cookies?: XCookie[] }>;
};

export const ElectronApiContext = createContext<ElectronApiContextProps>({
Expand Down
14 changes: 14 additions & 0 deletions frontend/types/Cookies.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* Cookies returned by agent-twitter-client
* scraper.getCookies()
*/
export type XCookie = {
key: string;
value: string;
domain?: string;
path?: string;
secure?: boolean;
httpOnly?: boolean;
sameSite?: string;
expires?: string;
};
2 changes: 2 additions & 0 deletions operate/services/manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,7 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to
"TWIKIT_USERNAME",
"TWIKIT_EMAIL",
"TWIKIT_PASSWORD",
"TWIKIT_COOKIES",
"TWIKIT_COOKIES_PATH",
]
):
Expand All @@ -591,6 +592,7 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to
username=service.env_variables["TWIKIT_USERNAME"]["value"],
email=service.env_variables["TWIKIT_EMAIL"]["value"],
password=service.env_variables["TWIKIT_PASSWORD"]["value"],
cookies=service.env_variables["TWIKIT_COOKIES"]["value"],
cookies_path=cookies_path,
),
"TWIKIT_COOKIES_PATH": str(cookies_path),
Expand Down
19 changes: 14 additions & 5 deletions operate/services/utils/memeooorr.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def await_for_cookies() -> dict:


async def async_get_twitter_cookies(
username: str, email: str, password: str, cookies_path: Path
username: str, email: str, password: str, cookies: str, cookies_path: Path
) -> Optional[str]:
"""Verifies that the Twitter credentials are correct and get the cookies"""

Expand All @@ -59,13 +59,22 @@ async def async_get_twitter_cookies(
valid_cookies = False
cookies_path.parent.mkdir(exist_ok=True, parents=True)

# If cookies exist, try with those and validate
if cookies_path.exists():
if not valid_cookies and cookies:
print("Checking the provided cookies")
client.set_cookies(json.loads(cookies))
user = await client.user()
print(f"User from cookies: {user.screen_name}")
valid_cookies = user.screen_name == username

# If cookies file exist, try with those and validate
if not valid_cookies and cookies_path.exists():
print("Checking the cookies file")
with open(cookies_path, "r", encoding="utf-8") as cookies_file:
cookies = json.load(cookies_file)
client.set_cookies(cookies)

user = await client.user()
print(f"User from cookies file: {user.screen_name}")
valid_cookies = user.screen_name == username

if not valid_cookies:
Expand All @@ -89,9 +98,9 @@ async def async_get_twitter_cookies(


def get_twitter_cookies(
username: str, email: str, password: str, cookies_path: Path
username: str, email: str, password: str, cookies: str, cookies_path: Path
) -> Optional[str]:
"""get_twitter_cookies"""
return asyncio.run(
async_get_twitter_cookies(username, email, password, cookies_path)
async_get_twitter_cookies(username, email, password, cookies, cookies_path)
)

0 comments on commit aad5d7f

Please sign in to comment.