removed credentials fixed blocks

This commit is contained in:
SwiftyOS
2025-05-16 12:46:37 +02:00
parent f1b5128715
commit fdf4785ae2
9 changed files with 50 additions and 163 deletions

View File

@@ -6,6 +6,9 @@ from enum import Enum
from typing import Any, Dict, List, Optional, Union
from backend.util.request import Requests
from backend.util.settings import Settings
settings = Settings()
class AyrshareAPIException(Exception):
@@ -105,12 +108,11 @@ class AyrshareClient:
def __init__(
self,
api_key: str,
custom_requests: Optional[Requests] = None,
):
headers: Dict[str, str] = {
"Content-Type": "application/json",
"Authorization": f"Bearer {api_key}",
"Authorization": f"Bearer {settings.secrets.ayrshare_api_key}",
}
self.headers = headers

View File

@@ -1,34 +0,0 @@
from typing import Literal
from pydantic import SecretStr
from backend.data.model import APIKeyCredentials, CredentialsField, CredentialsMetaInput
from backend.integrations.providers import ProviderName
# Define the type of credentials input expected for Example API
AyrshareCredentials = APIKeyCredentials
AyrshareCredentialsInput = CredentialsMetaInput[
Literal[ProviderName.AYRSHARE], Literal["api_key"]
]
# Mock credentials for testing Example API integration
AYRSHARE_CREDENTIALS = APIKeyCredentials(
id="8274be87-67a7-445d-bbc3-d27a017100f0",
provider="ayrshare-provider",
api_key=SecretStr("mock-ayrshare-api-key"),
title="Mock Ayrshare API key",
expires_at=None,
)
# Dictionary representation of test credentials for input fields
AYRSHARE_CREDENTIALS_INPUT = {
"provider": AYRSHARE_CREDENTIALS.provider,
"id": AYRSHARE_CREDENTIALS.id,
"type": AYRSHARE_CREDENTIALS.type,
"title": AYRSHARE_CREDENTIALS.title,
}
def AyrshareCredentialsField() -> AyrshareCredentialsInput:
"""Creates an Ayrshare credentials input on a block."""
return CredentialsField(description="The Ayrshare integration requires an API Key.")

View File

@@ -2,7 +2,7 @@ import logging
from typing import List, Optional, Union
from pydantic import BaseModel, Field
from datetime import datetime
from backend.blocks.aryshare._api import (
AutoHashtag,
AutoRepost,
@@ -11,13 +11,10 @@ from backend.blocks.aryshare._api import (
FirstComment,
SocialPlatform,
)
from backend.blocks.aryshare._auth import AYRSHARE_CREDENTIALS
from backend.data.block import Block, BlockCategory, BlockOutput, BlockSchema
from backend.data.model import APIKeyCredentials, SchemaField
from backend.data.model import SchemaField
from backend.integrations.credentials_store import IntegrationCredentialsStore
from ._auth import AyrshareCredentialsField, AyrshareCredentialsInput
logger = logging.getLogger(__name__)
creads_store = IntegrationCredentialsStore()
@@ -44,69 +41,47 @@ class BaseAyrsharePostBlock(Block):
class Input(BlockSchema):
"""Base input model for Ayrshare social media posts."""
credentials: AyrshareCredentialsInput = AyrshareCredentialsField()
post: str = SchemaField(
description="The post text to be published", default="", advanced=False
)
media_urls: Optional[List[str]] = SchemaField(
description="Optional list of media URLs to include",
default=None,
media_urls: List[str] = SchemaField(
description="Optional list of media URLs to include. Set is_video in advanced settings to true if you want to upload videos.",
default_factory=list,
advanced=False,
)
is_video: Optional[bool] = SchemaField(
description="Whether the media is a video", default=None, advanced=False
is_video: bool = SchemaField(
description="Whether the media is a video", default=False, advanced=True
)
schedule_date: Optional[str] = SchemaField(
schedule_date: Optional[datetime] = SchemaField(
description="UTC datetime for scheduling (YYYY-MM-DDThh:mm:ssZ)",
default=None,
advanced=False,
advanced=True,
)
first_comment: Optional[FirstComment] = SchemaField(
description="Configuration for first comment", default=None, advanced=False
disable_comments: bool = SchemaField(
description="Whether to disable comments", default=False, advanced=True
)
disable_comments: Optional[bool] = SchemaField(
description="Whether to disable comments", default=None, advanced=False
)
shorten_links: Optional[bool] = SchemaField(
description="Whether to shorten links", default=None, advanced=False
)
auto_schedule: Optional[AutoSchedule] = SchemaField(
description="Configuration for automatic scheduling",
default=None,
advanced=False,
)
auto_repost: Optional[AutoRepost] = SchemaField(
description="Configuration for automatic reposting",
default=None,
advanced=False,
)
auto_hashtag: Optional[Union[AutoHashtag, bool]] = SchemaField(
description="Configuration for automatic hashtags",
default=None,
advanced=False,
shorten_links: bool = SchemaField(
description="Whether to shorten links", default=False, advanced=True
)
unsplash: Optional[str] = SchemaField(
description="Unsplash image configuration", default=None, advanced=False
description="Unsplash image configuration", default=None, advanced=True
)
requires_approval: Optional[bool] = SchemaField(
requires_approval: bool = SchemaField(
description="Whether to enable approval workflow",
default=None,
advanced=False,
default=False,
advanced=True,
)
random_post: Optional[bool] = SchemaField(
random_post: bool= SchemaField(
description="Whether to generate random post text",
default=None,
advanced=False,
default=False,
advanced=True,
)
random_media_url: Optional[bool] = SchemaField(
description="Whether to generate random media", default=None, advanced=False
)
idempotency_key: Optional[str] = SchemaField(
description="Unique ID for the post", default=None, advanced=False
random_media_url: bool = SchemaField(
description="Whether to generate random media", default=False, advanced=True
)
notes: Optional[str] = SchemaField(
description="Additional notes for the post", default=None, advanced=False
description="Additional notes for the post", default=None, advanced=True
)
class Output(BlockSchema):
@@ -146,21 +121,11 @@ class BaseAyrsharePostBlock(Block):
input_schema=BaseAyrsharePostBlock.Input,
# The schema, defined as a Pydantic model, for the output data.
output_schema=BaseAyrsharePostBlock.Output,
# The credentials required for testing the block.
# This is an instance of APIKeyCredentials with sample values.
test_credentials=AYRSHARE_CREDENTIALS,
# The list or single sample input data for the block, for testing.
# This is an instance of the Input schema with sample values.
test_input={
"post": "Hello, world! This is a test post.",
"media_urls": ["https://example.com/image.jpg"],
"is_video": False,
"credentials": {
"provider": "ayrshare",
"id": AYRSHARE_CREDENTIALS.id,
"type": AYRSHARE_CREDENTIALS.type,
"title": AYRSHARE_CREDENTIALS.title,
},
},
# The list or single expected output if the test_input is run.
# Each output is a tuple of (output_name, output_data).
@@ -183,37 +148,30 @@ class BaseAyrsharePostBlock(Block):
)
@staticmethod
def create_client(credentials):
return AyrshareClient(
api_key=credentials.api_key.get_secret_value(),
)
def create_client():
return AyrshareClient()
def _create_post(
self,
input_data: "BaseAyrsharePostBlock.Input",
platforms: List[SocialPlatform],
profile_key: Optional[str] = None,
credentials: Optional[APIKeyCredentials] = None,
) -> RequestOutput:
client = self.create_client(credentials)
client = self.create_client()
"""Create a post on the specified platforms."""
iso_date = input_data.schedule_date.isoformat() if input_data.schedule_date else None
response = client.create_post(
post=input_data.post,
platforms=platforms,
media_urls=input_data.media_urls,
is_video=input_data.is_video,
schedule_date=input_data.schedule_date,
first_comment=input_data.first_comment,
schedule_date=iso_date,
disable_comments=input_data.disable_comments,
shorten_links=input_data.shorten_links,
auto_schedule=input_data.auto_schedule,
auto_repost=input_data.auto_repost,
auto_hashtag=input_data.auto_hashtag,
unsplash=input_data.unsplash,
requires_approval=input_data.requires_approval,
random_post=input_data.random_post,
random_media_url=input_data.random_media_url,
idempotency_key=input_data.idempotency_key,
notes=input_data.notes,
profile_key=profile_key,
)
@@ -233,16 +191,12 @@ class BaseAyrsharePostBlock(Block):
def run(
self,
input_data: "BaseAyrsharePostBlock.Input",
*,
credentials: APIKeyCredentials,
**kwargs,
) -> BlockOutput:
"""Run the block."""
platforms = [SocialPlatform.FACEBOOK]
yield "post_result", self._create_post(
input_data, platforms=platforms, credentials=credentials
)
yield "post_result", self._create_post(input_data, platforms=platforms)
class PostToFacebookBlock(BaseAyrsharePostBlock):
@@ -251,7 +205,7 @@ class PostToFacebookBlock(BaseAyrsharePostBlock):
def __init__(self):
super().__init__(
id="3352f512-3524-49ed-a08f-003042da2fc1",
description="Post to Facebook",
description="Post to Facebook using Ayrshare",
)
def run(
@@ -259,7 +213,6 @@ class PostToFacebookBlock(BaseAyrsharePostBlock):
input_data: BaseAyrsharePostBlock.Input,
*,
user_id: str,
credentials: APIKeyCredentials,
**kwargs,
) -> BlockOutput:
"""Post to Facebook."""
@@ -272,18 +225,17 @@ class PostToFacebookBlock(BaseAyrsharePostBlock):
input_data,
[SocialPlatform.FACEBOOK],
profile_key=profile_key_value,
credentials=credentials,
)
yield "post_result", post_result
class PostToTwitterBlock(BaseAyrsharePostBlock):
"""Block for posting to Twitter."""
class PostToXBlock(BaseAyrsharePostBlock):
"""Block for posting to X / Twitter."""
def __init__(self):
super().__init__(
id="9e8f844e-b4a5-4b25-80f2-9e1dd7d67625",
description="Post to Twitter",
description="Post to X / Twitter using Ayrshare",
)
def run(
@@ -291,7 +243,6 @@ class PostToTwitterBlock(BaseAyrsharePostBlock):
input_data: BaseAyrsharePostBlock.Input,
*,
user_id: str,
credentials: APIKeyCredentials,
**kwargs,
) -> BlockOutput:
"""Post to Twitter."""
@@ -304,7 +255,6 @@ class PostToTwitterBlock(BaseAyrsharePostBlock):
input_data,
[SocialPlatform.TWITTER],
profile_key=profile_key_value,
credentials=credentials,
)
yield "post_result", post_result
@@ -315,7 +265,7 @@ class PostToLinkedInBlock(BaseAyrsharePostBlock):
def __init__(self):
super().__init__(
id="589af4e4-507f-42fd-b9ac-a67ecef25811",
description="Post to LinkedIn",
description="Post to LinkedIn using Ayrshare",
)
def run(
@@ -323,7 +273,6 @@ class PostToLinkedInBlock(BaseAyrsharePostBlock):
input_data: BaseAyrsharePostBlock.Input,
*,
user_id: str,
credentials: APIKeyCredentials,
**kwargs,
) -> BlockOutput:
"""Post to LinkedIn."""
@@ -336,7 +285,6 @@ class PostToLinkedInBlock(BaseAyrsharePostBlock):
input_data,
[SocialPlatform.LINKEDIN],
profile_key=profile_key_value,
credentials=credentials,
)
yield "post_result", post_result
@@ -347,7 +295,7 @@ class PostToInstagramBlock(BaseAyrsharePostBlock):
def __init__(self):
super().__init__(
id="89b02b96-a7cb-46f4-9900-c48b32fe1552",
description="Post to Instagram",
description="Post to Instagram using Ayrshare",
)
def run(
@@ -355,7 +303,6 @@ class PostToInstagramBlock(BaseAyrsharePostBlock):
input_data: BaseAyrsharePostBlock.Input,
*,
user_id: str,
credentials: APIKeyCredentials,
**kwargs,
) -> BlockOutput:
"""Post to Instagram."""
@@ -368,7 +315,6 @@ class PostToInstagramBlock(BaseAyrsharePostBlock):
input_data,
[SocialPlatform.INSTAGRAM],
profile_key=profile_key_value,
credentials=credentials,
)
yield "post_result", post_result
@@ -379,7 +325,7 @@ class PostToYouTubeBlock(BaseAyrsharePostBlock):
def __init__(self):
super().__init__(
id="0082d712-ff1b-4c3d-8a8d-6c7721883b83",
description="Post to YouTube",
description="Post to YouTube using Ayrshare",
)
def run(
@@ -387,7 +333,6 @@ class PostToYouTubeBlock(BaseAyrsharePostBlock):
input_data: BaseAyrsharePostBlock.Input,
*,
user_id: str,
credentials: APIKeyCredentials,
**kwargs,
) -> BlockOutput:
"""Post to YouTube."""
@@ -400,7 +345,6 @@ class PostToYouTubeBlock(BaseAyrsharePostBlock):
input_data,
[SocialPlatform.YOUTUBE],
profile_key=profile_key_value,
credentials=credentials,
)
yield "post_result", post_result
@@ -411,7 +355,7 @@ class PostToRedditBlock(BaseAyrsharePostBlock):
def __init__(self):
super().__init__(
id="c7733580-3c72-483e-8e47-a8d58754d853",
description="Post to Reddit",
description="Post to Reddit using Ayrshare",
)
def run(
@@ -419,7 +363,6 @@ class PostToRedditBlock(BaseAyrsharePostBlock):
input_data: BaseAyrsharePostBlock.Input,
*,
user_id: str,
credentials: APIKeyCredentials,
**kwargs,
) -> BlockOutput:
"""Post to Reddit."""
@@ -432,7 +375,6 @@ class PostToRedditBlock(BaseAyrsharePostBlock):
input_data,
[SocialPlatform.REDDIT],
profile_key=profile_key_value,
credentials=credentials,
)
yield "post_result", post_result
@@ -443,7 +385,7 @@ class PostToTelegramBlock(BaseAyrsharePostBlock):
def __init__(self):
super().__init__(
id="47bc74eb-4af2-452c-b933-af377c7287df",
description="Post to Telegram",
description="Post to Telegram using Ayrshare",
)
def run(
@@ -451,7 +393,6 @@ class PostToTelegramBlock(BaseAyrsharePostBlock):
input_data: BaseAyrsharePostBlock.Input,
*,
user_id: str,
credentials: APIKeyCredentials,
**kwargs,
) -> BlockOutput:
"""Post to Telegram."""
@@ -464,7 +405,6 @@ class PostToTelegramBlock(BaseAyrsharePostBlock):
input_data,
[SocialPlatform.TELEGRAM],
profile_key=profile_key_value,
credentials=credentials,
)
yield "post_result", post_result
@@ -475,7 +415,7 @@ class PostToGMBBlock(BaseAyrsharePostBlock):
def __init__(self):
super().__init__(
id="2c38c783-c484-4503-9280-ef5d1d345a7e",
description="Post to Google My Business",
description="Post to Google My Business using Ayrshare",
)
def run(
@@ -483,7 +423,6 @@ class PostToGMBBlock(BaseAyrsharePostBlock):
input_data: BaseAyrsharePostBlock.Input,
*,
user_id: str,
credentials: APIKeyCredentials,
**kwargs,
) -> BlockOutput:
"""Post to Google My Business."""
@@ -496,7 +435,6 @@ class PostToGMBBlock(BaseAyrsharePostBlock):
input_data,
[SocialPlatform.GMB],
profile_key=profile_key_value,
credentials=credentials,
)
yield "post_result", post_result
@@ -507,7 +445,7 @@ class PostToPinterestBlock(BaseAyrsharePostBlock):
def __init__(self):
super().__init__(
id="3ca46e05-dbaa-4afb-9e95-5a429c4177e6",
description="Post to Pinterest",
description="Post to Pinterest using Ayrshare",
)
def run(
@@ -515,7 +453,6 @@ class PostToPinterestBlock(BaseAyrsharePostBlock):
input_data: BaseAyrsharePostBlock.Input,
*,
user_id: str,
credentials: APIKeyCredentials,
**kwargs,
) -> BlockOutput:
"""Post to Pinterest."""
@@ -528,7 +465,6 @@ class PostToPinterestBlock(BaseAyrsharePostBlock):
input_data,
[SocialPlatform.PINTEREST],
profile_key=profile_key_value,
credentials=credentials,
)
yield "post_result", post_result
@@ -539,7 +475,7 @@ class PostToTikTokBlock(BaseAyrsharePostBlock):
def __init__(self):
super().__init__(
id="7faf4b27-96b0-4f05-bf64-e0de54ae74e1",
description="Post to TikTok",
description="Post to TikTok using Ayrshare",
)
def run(
@@ -547,7 +483,6 @@ class PostToTikTokBlock(BaseAyrsharePostBlock):
input_data: BaseAyrsharePostBlock.Input,
*,
user_id: str,
credentials: APIKeyCredentials,
**kwargs,
) -> BlockOutput:
"""Post to TikTok."""
@@ -560,7 +495,6 @@ class PostToTikTokBlock(BaseAyrsharePostBlock):
input_data,
[SocialPlatform.TIKTOK],
profile_key=profile_key_value,
credentials=credentials,
)
yield "post_result", post_result
@@ -571,7 +505,7 @@ class PostToBlueskyBlock(BaseAyrsharePostBlock):
def __init__(self):
super().__init__(
id="cbd52c2a-06d2-43ed-9560-6576cc163283",
description="Post to Bluesky",
description="Post to Bluesky using Ayrshare",
)
def run(
@@ -579,7 +513,6 @@ class PostToBlueskyBlock(BaseAyrsharePostBlock):
input_data: BaseAyrsharePostBlock.Input,
*,
user_id: str,
credentials: APIKeyCredentials,
**kwargs,
) -> BlockOutput:
"""Post to Bluesky."""
@@ -592,6 +525,5 @@ class PostToBlueskyBlock(BaseAyrsharePostBlock):
input_data,
[SocialPlatform.BLUESKY],
profile_key=profile_key_value,
credentials=credentials,
)
yield "post_result", post_result

View File

@@ -178,13 +178,6 @@ zerobounce_credentials = APIKeyCredentials(
expires_at=None,
)
ayrshare_credentials = APIKeyCredentials(
id="0883fd5f-6f4e-4013-82b1-39e31baa5345",
provider="ayrshare",
api_key=SecretStr(settings.secrets.ayrshare_api_key),
title="Use Credits for Ayrshare",
expires_at=None,
)
llama_api_credentials = APIKeyCredentials(
id="d44045af-1c33-4833-9e19-752313214de2",
@@ -215,7 +208,6 @@ DEFAULT_CREDENTIALS = [
apollo_credentials,
smartlead_credentials,
zerobounce_credentials,
ayrshare_credentials,
google_maps_credentials,
]
@@ -294,8 +286,6 @@ class IntegrationCredentialsStore:
all_credentials.append(zerobounce_credentials)
if settings.secrets.google_maps_api_key:
all_credentials.append(google_maps_credentials)
if settings.secrets.ayrshare_api_key:
all_credentials.append(ayrshare_credentials)
if settings.secrets.llama_api_key:
all_credentials.append(llama_api_credentials)
return all_credentials

View File

@@ -41,5 +41,4 @@ class ProviderName(str, Enum):
TODOIST = "todoist"
UNREAL_SPEECH = "unreal_speech"
ZEROBOUNCE = "zerobounce"
AYRSHARE = "ayrshare"
# --8<-- [end:ProviderName]

View File

@@ -82,6 +82,7 @@ async def test_get_library_agents(mocker):
@pytest.mark.asyncio(loop_scope="session")
@pytest.mark.skip(reason="Test not implemented yet")
async def test_add_agent_to_library(mocker):
await connect()
# Mock data

View File

@@ -91,8 +91,7 @@ export const providerIcons: Record<
hubspot: FaHubspot,
smartlead: fallbackIcon,
todoist: fallbackIcon,
zerobounce: fallbackIcon,
ayrshare: fallbackIcon,
zerobounce: fallbackIcon
};
// --8<-- [end:ProviderIconsEmbed]

View File

@@ -53,7 +53,6 @@ const providerDisplayNames: Record<CredentialsProviderName, string> = {
todoist: "Todoist",
unreal_speech: "Unreal Speech",
zerobounce: "ZeroBounce",
ayrshare: "Ayrshare",
} as const;
// --8<-- [end:CredentialsProviderNames]
@@ -102,7 +101,7 @@ export default function CredentialsProvider({
children: React.ReactNode;
}) {
const [providers, setProviders] =
useState<CredentialsProvidersContextType | null>(null);
useState<CredentialsProvidersContextType>({});
const api = useBackendAPI();
const addCredentials = useCallback(

View File

@@ -185,7 +185,6 @@ export const PROVIDER_NAMES = {
UNREAL_SPEECH: "unreal_speech",
TODOIST: "todoist",
ZEROBOUNCE: "zerobounce",
AYRSHARE: "ayrshare",
} as const;
// --8<-- [end:BlockIOCredentialsSubSchema]