+
    CiB                        R t ^ RIt^ RIt^ RIt^ RIt^ RIHt ^ RIHtH	t	H
t
 ^ RIHt ^ RIt ^ RIt ^ RIHt ^ RIt ^ RIHt ^ RIHt  ^ RIHt ^ R	IHt  ^ RIt] ! R
 R4      4       t]P<                  ! ]4      t ]PB                  ! 4       t"]PF                  ! R4      t$]"PK                  ]$4       ] PM                  ]"4       ] PO                  ]PP                  4        ! R R4      t) ! R R4      t* ! R R4      t+ ! R R4      t, ! R R4      t- ! R R4      t.]R8X  d   ^ RI/t/]! 4       t0].! ]04      t1]1Pe                  4        ]3! ]/Ph                  4      ^8  d6   RPk                  ]/Ph                  R,          4      t6]1Po                  ]64       R# ]8! R4       ]8! R4       ]8! R4       R# R#   ] d    Rt ELi ; i  ] d	    RtRt ELi ; i  ] d	    RtRt ELi ; i  ] d	    RtRt ELi ; i  ] d    Rt ELi ; i)ul   
ArtifyBot — Etsy Product Automation Framework
Secure, modular version with proper credential management.
N)Path)OptionalDictList)	dataclass)Image)build)Credentials)	webdriver)Optionsc                     a  ] tR t^5t o Rt]! ]P                  P                  R4      4      t	]! ]
P                  ! 4       4      t]! ]P                  P                  R4      4      tRtRtRtRtRtRt^t^tR tR tV 3R ltR	tV tR# )
ArtifyConfigzConfiguration for ArtifyBot.z~/Documents/ArtifyBotz~/Documents/ArtifyBot/outputN,  c                    V P                   P                  RRR7       V P                  P                  RRR7       V P                  4        R# )z(Create directories and load credentials.T)parentsexist_okN)base_dirmkdir
output_dirload_from_envselfs   &artifybot.py__post_init__ArtifyConfig.__post_init__J   s<    D48dT:    c                   V P                   R,          pVP                  4       '       d   \        V4      ;_uu_ 4       pV Fo  pRV9   g   K  VP                  4       P	                  R4      '       d   K3  VP                  4       P                  R^4      w  rE\        WP                  4       V4       Kq  	  RRR4       R# R#   + '       g   i     R# ; i)z Load credentials from .env file.z.env=#N)r   existsopenstrip
startswithsplitsetattrlower)r   env_pathflinekeyvals   &     r   r   ArtifyConfig.load_from_envP   s    ==6)??h1Dd{4::<+B+B3+G+G#'::<#5#5c1#=iik37    s   
B?"B?3A B??C	c                   < V ^8  d   Qh/ S[ ;R&   S[ ;R&   S[ ;R&   S[S[,          ;R&   S[S[,          ;R&   S[S[,          ;R&   S[S[,          ;R&   S[S[,          ;R&   S[;R	&   S[;R
&   S[;R&   # )   r   work_dirr   
openai_keydiscord_tokenetsy_api_keyetsy_shop_idgoogle_drive_creds_file	image_dpiimage_width_inchesimage_height_inches)r   r   strint)format__classdict__s   "r   __annotate__ArtifyConfig.__annotate__5   s     
 F  0  O  $  C='  3-&  3-&  &c]1 " # $  % & !' r    )__name__
__module____qualname____firstlineno____doc__r   ospath
expanduserr   tempfile
gettempdirr.   r   r/   r0   r1   r2   r3   r4   r5   r6   r   r   __annotate_func____static_attributes____classdictcell__r:   s   @r   r   r   5   s     & "'',,-DEFH(--/0HBGG../MNOJ !%J#'M"&L"&L-1 I !87  r   r   z4%(asctime)s - %(name)s - %(levelname)s - %(message)sc                   `   a  ] tR t^kt o Rt]V 3R lR l4       t]RV 3R lR ll4       tRtV t	R# )	ImageProcessorz-Handle image conversions, cropping, resizing.c                &   < V ^8  d   QhRS[ RS[ /# )r-   	webp_pathreturnr7   )r9   r:   s   "r   r;   ImageProcessor.__annotate__o   s      s s r   c                   \         '       g   \        R4      h\        V 4      p V P                  R4      p \         P                  ! V 4      ;_uu_ 4       pVP                  R4      P                  VR4       RRR4       \        P                  RV P                   RVP                   24       \        V4      #   + '       g   i     LJ; i  \         d   p\        P                  RT 24       h Rp?ii ; i)	zConvert WebP to PNG.z$Pillow required for image conversionz.pngRGBPNGNz
Converted u    → zConversion failed: )r   ImportErrorr   with_suffixr    convertsaveloggerinfonamer7   	Exceptionerror)rO   png_pathimges   &   r   convert_webp_to_png"ImageProcessor.convert_webp_to_pngn   s     uDEEO	((0	I&&#E"''%8 'KK*Y^^$4E(--IJx=  '&  	LL.qc23	s0   C
 "B75AC
 7C	C
 
C3C..C3c          
      8   < V ^8  d   QhRS[ RS[RS[RS[ RS[ /# )r-   
image_pathwidthheightaspect_namerP   r7   float)r9   r:   s   "r   r;   rR      s2     + +# +e +U +#&+03+r   c           	        \         '       g   \        R4      h \         P                  ! V 4      pVf   \        RV  24      hRpWR,          VP                  ^ ,          ,          pWQ,          VP                  ^,          ,          p\         P
                  ! VRWvR7      pVP                  R,          w  rW,          p
W,          pW8  d   T	p\        W,          4      pMTp\        W,          4      pW,
          ^,          pW,
          ^,          pWOW,           1WV,           13,          p\        V 4      pV'       d   RV 2MRpVP                  VP                  V,           4      p\         P                  ! \        V4      V\         P                  ^d.4       \        P                  R	VP                   R
V RV R24       \        V4      #   \          d   p\        P#                  RT 24       h Rp?ii ; i)z$Crop image to specific aspect ratio.z)opencv-python required for image croppingNzCannot read image: r   )fxfy:Nr-   N_ zCropped z to    ×z aspectzCropping failed: )    rq   )cv2rV   imreadFileNotFoundErrorshaperesizer8   r   	with_stemstemimwriter7   IMWRITE_JPEG_QUALITYrZ   r[   r\   r]   r^   )re   rf   rg   rh   r`   dpitarget_height_pxtarget_width_pximg_himg_wtarget_ratio	img_ratiocrop_wcrop_hstart_xstart_ycroppedoutput_pathsuffixoutra   s   &&&&                 r   crop_to_ratioImageProcessor.crop_to_ratio   s    sIJJ%	**Z(C{'*=j\(JKK C"|ciil:!kCIIaL8O**S&_RC 99R=LE >LI'U12U12~!+G~!+G'.0'&.2HHIG z*K*5q&2F''(8(86(ABCKKC'C,D,Dc+JKKK(;#3#3"4Dr&QRs8O 	LL,QC01	s   F-G G0G++G0r=   N)ro   )
r>   r?   r@   rA   rB   staticmethodrb   r   rI   rJ   rK   s   @r   rM   rM   k   s3     7 " + + +r   rM   c                   Z   a  ] tR t^t o RtV 3R lR ltV 3R lR ltV 3R lR ltRtV t	R	# )
DiscordIntegrationz-Discord API for MidJourney prompt automation.c                    < V ^8  d   QhRS[ /# )r-   tokenrQ   )r9   r:   s   "r   r;   DiscordIntegration.__annotate__   s     5 5c 5r   c                N    \         '       g   \        R 4      hWn        RV n        R# )z)requests required for Discord integrationzhttps://discord.com/api/v9N)requestsrV   r   base_url)r   r   s   &&r   __init__DiscordIntegration.__init__   s    xIJJ
4r   c                ,   < V ^8  d   QhRS[ RS[ RS[/# )r-   
channel_idpromptrP   )r7   bool)r9   r:   s   "r   r;   r      s"      c 3 4 r   c                    RV P                   /pRRV 2/p\        P                  ! V P                   RV R2VV^
R7      pVP                  ^8X  d   \
        P                  RV 24       R# \
        P                  R	VP                   R
VP                   24       R#   \         d$   p\
        P                  RT 24        Rp?R# Rp?ii ; i)z(Send /imagine prompt to Discord channel.authorizationcontentz/imagine prompt 
/channels/	/messagesjsonheaderstimeoutzSent prompt to Discord channel TDiscord error:  - FzFailed to send prompt: N)
r   r   postr   status_coderZ   r[   r^   textr]   )r   r   r   r   payloadrespra   s   &&&    r   send_promptDiscordIntegration.send_prompt   s    	&

3G $4VH"=>G====/J<yA	D 3&=j\JKt/?/?.@DII;OP 	LL21#67	s   A(B ,/B C(CCc                6   < V ^8  d   QhRS[ RS[S[ ,          /# )r-   r   rP   r7   r   )r9   r:   s   "r   r;   r      s        S  Xc]  r   c                H    RV P                   /p\        P                  ! V P                   RV R2V^
R7      pVP                  ^8w  d%   \
        P                  RVP                   24       R# VP                  4       pV F  pVP                  R4      '       g   K  VR,          ^ ,          pVR,          pVP                  R	R
4      p\        P                  ! V^
R7      p	V	P                  ^8X  g   Kr  \        \        P                  ! 4       4      V,          p
V
P                  V	P                  4       \
        P                  RV 24       \        V
4      u # 	  \
        P                  RV 24       R#   \          d$   p\
        P                  RT 24        Rp?R# Rp?ii ; i)z.Download latest image attachment from channel.r   r   r   )r   r   r   Nattachmentsurlfilenameimage)r   zDownloaded image: z No attachments found in channel zFailed to fetch image: )r   r   getr   r   rZ   r^   r   r   rF   rG   write_bytesr   r[   r7   warningr]   )r   r   r   r   messagesmsg
attachmentr   r   img_respoutputra   s   &&          r   fetch_latest_image%DiscordIntegration.fetch_latest_image   sa   	&

3G<<==/J<yAD
 3&t/?/?.@AByy{H77=))!$]!3A!6J$U+C)~~j'BH  (||C<H++s2!%h&9&9&;!<x!G**8+;+;<&8
$CD"6{*   NN=j\JK 	LL21#67	s2   A*E3 .)E3 AE3 2A$E3 E3 3F!>FF!)r   r   N)
r>   r?   r@   rA   rB   r   r   r   rI   rJ   rK   s   @r   r   r      s&     75 5 *   r   r   c                   ^   a  ] tR t^t o RtV 3R lR ltR
V 3R lR lltV 3R lR ltR	tV t	R# )GoogleDriveIntegrationz%Google Drive API for file management.c                    < V ^8  d   QhRS[ /# )r-   credentials_filerQ   )r9   r:   s   "r   r;   #GoogleDriveIntegration.__annotate__   s     D D Dr   c                   \         '       d   \        '       g   \        R 4      h\        V4      pVP	                  4       '       g   \        RV 24      h\        V4      ;_uu_ 4       p\        P                  ! V4      pRRR4       \        P                  ! XR.4      V n
        \        RRV P                  R7      V n        R#   + '       g   i     LL; i)z!google-api-python-client requiredzCredentials file not found: Nz%https://www.googleapis.com/auth/drivedrivev3)credentials)r   GoogleCredentialsrV   r   r   rt   r    r   loadfrom_authorized_user_infocredsservice)r   r   	cred_pathr'   	cred_infos   &&   r   r   GoogleDriveIntegration.__init__   s    u--ABB)*	!!#&BCSBT$UVV)__		!I  '@@45

 Wd

C _s   &CC	Nc                <   < V ^8  d   QhRS[ RS[S[ ,          RS[ /# )r-   folder_name	parent_idrP   r   )r9   r:   s   "r   r;   r     s'       # RU r   c                T    RVRR/pV'       d   V.VR&   V P                   P                  4       P                  VRR7      P                  4       pVP	                  R4      p\
        P                  RV RV R	24       V#   \         d   p\
        P                  R
T 24       h Rp?ii ; i)zCreate folder in Google Drive.r\   mimeTypez"application/vnd.google-apps.folderr   id)bodyfieldszCreated folder: z ()zFailed to create folder: N)	r   filescreateexecuter   rZ   r[   r]   r^   )r   r   r   metadatafolder	folder_idra   s   &&&    r   create_folder$GoogleDriveIntegration.create_folder  s    	@H '0k#\\'')00ht0LTTVF

4(IKK*;-r)AFG 	LL4QC89	s   A> A-A> >B'	B""B'c                ,   < V ^8  d   QhRS[ RS[ RS[ /# )r-   	file_pathr   rP   rQ   )r9   r:   s   "r   r;   r     s"      S S S r   c                    ^ RI Hp \        V4      pRVP                  RV./pV! \	        V4      RR7      pV P
                  P                  4       P                  WERR7      P                  4       p\        P                  RVP                   24       VP                  R4      #   \         d   p\        P                  R	T 24       h R
p?ii ; i)zUpload file to Google Drive.)MediaFileUploadr\   r   z*/*)mimetyper   )r   
media_bodyr   z
Uploaded: zFailed to upload file: N)googleapiclient.httpr   r   r\   r7   r   r   r   r   rZ   r[   r   r]   r^   )r   r   r   r   r   mediafilera   s   &&&     r   upload_file"GoogleDriveIntegration.upload_file  s    	<YI	I;H
 $C	NUCE<<%%'..HW[.\ddfDKK*Y^^$45688D>! 	LL21#67	s   B B# #C.CC)r   r   N)
r>   r?   r@   rA   rB   r   r   r   rI   rJ   rK   s   @r   r   r      s(     /D D" $ r   r   c                   L   a  ] tR tRt o RtV 3R lR ltR	V 3R lR lltRtV tR# )
EtsyIntegrationi6  zEtsy API for product listings.c                &   < V ^8  d   QhRS[ RS[ /# )r-   api_keyshop_idrQ   )r9   r:   s   "r   r;   EtsyIntegration.__annotate__9  s     6 6 6c 6r   c                Z    \         '       g   \        R 4      hWn        W n        RV n        R# )zrequests required for Etsy APIzhttps://openapi.etsy.com/v3N)r   rV   r   r   r   )r   r   r   s   &&&r   r   EtsyIntegration.__init__9  s$    x>??5r   Nc          
      H   < V ^8  d   QhRS[ RS[ RS[RS[S[ ,          RS[/# )r-   titledescriptionpricetagsrP   )r7   rj   r   r   )r9   r:   s   "r   r;   r   @  s6     " "C "c "% "!#Y"26"r   c                    RRV P                    2RR/pRTRTRTRR	R
RRT;'       g    . /p\        P                  ! V P                   RV P                   R2VV^R7      pVP
                  R9   d;   VP                  4       P                  R/ 4      p\        P                  RV 24       V# \        P                  RVP
                   RVP                   24       / #   \         d   p	\        P                  RT	 24       h Rp	?	ii ; i)z#Create new product listing on Etsy.AuthorizationzBearer zContent-Typezapplication/jsonr   r   r   quantityi  should_auto_renewTr   z/shops/z	/listingsr   datazCreated Etsy listing: zEtsy error: r   zFailed to create listing: N)      )r   r   r   r   r   r   r   r   rZ   r[   r^   r   r]   )
r   r   r   r   r   r   r   r   listingra   s
   &&&&&     r   create_listingEtsyIntegration.create_listing@  s   	74<<.!9 2G {C#T

G ====/i@	D :-))+//&"54UG<=|D,<,<+=SLM	 	LL5aS9:	s#   &C BC ,0C D(DD)r   r   r   r   )	r>   r?   r@   rA   rB   r   r  rI   rJ   rK   s   @r   r   r   6  s!     (6 6" " "r   r   c                   L   a  ] tR tRt o RtV 3R lR ltR	V 3R lR lltRtV tR# )
PromptGeneratorii  z'Generate creative prompts using OpenAI.c                    < V ^8  d   QhRS[ /# )r-   r   rQ   )r9   r:   s   "r   r;   PromptGenerator.__annotate__l  s     ! ! !r   c                J    \         '       g   \        R 4      hV\         n        R# )z%openai required for prompt generationN)openairV   r   )r   r   s   &&r   r   PromptGenerator.__init__l  s    vEFF r   c          	      B   < V ^8  d   QhRS[ RS[ RS[RS[S[ ,          /# )r-   topicstylecountrP   )r7   r8   r   )r9   r:   s   "r   r;   r  q  s/      c # $(Ir   c                    RV RV RV R2p\         P                  P                  RRRRV/.R	R
R7      pVR,          ^ ,          R,          R,          p^ RIpVP	                  RWgP
                  4      pV'       dI   \        P                  ! VP                  4       4      p	\        P                  R\        V	4       R24       V	# \        P                  R4       V.#   \         d   p
\        P                  RT
 24       h Rp
?
ii ; i)zGenerate creative prompts.zBYou are a creative prompt generator for digital artists.
Generate z unique, detailed prompts for z in the theme of: zl
Each prompt should be vivid, specific, and suitable for MidJourney/DALL-E.
Return as JSON array of strings.zgpt-3.5-turboroleuserr   g?i  )modelr   temperature
max_tokenschoicesmessageNz\[.*\]z
Generated z promptsz!Could not parse generated promptszPrompt generation failed: )r  ChatCompletionr   researchDOTALLr   loadsgrouprZ   r[   lenr   r]   r^   )r   r  r  r  
system_msgresponser   r  matchpromptsra   s   &&&&       r   generatePromptGenerator.generateq  s   	

.ug5Gw O!$J
 ,,33%!69jAB	 4 H y)!,Y7	BGIIi))<E**U[[]3jWh?@BCy  	LL5aS9:	s   CC C D'D  Dr=   N)zdigital art   )	r>   r?   r@   rA   rB   r   r!  rI   rJ   rK   s   @r   r  r  i  s!     1! !
  r   r  c                   V   a  ] tR tRt o RtR
V 3R lR lltR tRV 3R lR lltR	tV t	R# )	ArtifyBoti  z0Main orchestration for Etsy automation workflow.Nc                0   < V ^8  d   QhRS[ S[,          /# )r-   config)r   r   )r9   r:   s   "r   r;   ArtifyBot.__annotate__  s     0 0x5 0r   c                    T;'       g    \        4       V n        R V n        R V n        R V n        R V n        \        4       V n        R # r   )r   r'  discordgoogle_driveetsy
prompt_genrM   image_processor)r   r'  s   &&r   r   ArtifyBot.__init__  s;    .. 	-/r   c                   V P                   P                  '       d%   \        V P                   P                  4      V n        V P                   P                  '       d%   \        V P                   P                  4      V n        V P                   P                  '       dV   V P                   P                  '       d:   \        V P                   P                  V P                   P                  4      V n
        V P                   P                  '       d%   \        V P                   P                  4      V n        \        P                  R4       R# )zInitialize all integrations.zArtifyBot initializedN)r'  r0   r   r*  r3   r   r+  r1   r2   r   r,  r/   r  r-  rZ   r[   r   s   &r   
initializeArtifyBot.initialize  s    ;;$$$-dkk.G.GHDL;;... 6t{{7Z7Z [D;;###(@(@(@'(@(@$++BZBZ[DI;;!!!-dkk.D.DEDO+,r   c                &   < V ^8  d   QhRS[ RS[/# )r-   r  r   ri   )r9   r:   s   "r   r;   r(    s       E r   c                    V P                   '       g   \        P                  R4       R# V P                   P                  V^R7      p\        P	                  RV^ ,           24       V P
                  '       d9   V P
                  P                  \        P                  ! RR4      V^ ,          4       \        P	                  RV 24       R#   \         d$   p\        P                  R	T 24        R
p?R# R
p?ii ; i)uD   Complete workflow: generate prompts → get images → list on Etsy.zOpenAI not configuredF)r  zGenerated prompt: MIDJOURNEY_CHANNEL_IDro   zWorkflow started for: TzWorkflow failed: N)
r-  rZ   r^   r!  r[   r*  r   rC   getenvr]   )r   r  r   r   ra   s   &&&  r   workflow_generate_and_list$ArtifyBot.workflow_generate_and_list  s    	???45 oo..uA.>GKK,WQZL9: |||((3JB)OQXYZQ[\KK089 	LL,QC01	s)   C C AC 9AC C9C44C9)r'  r*  r,  r+  r.  r-  r   )g{G#@)
r>   r?   r@   rA   rB   r   r1  r7  rI   rJ   rK   s   @r   r%  r%    s&     :0 0-   r   r%  __main__ :   NNzArtifyBot CLI - Usage:z  python artifybot.py <topic>zW
Requirements: Set environment variables in ~/.openclaw/workspace/skills/artifybot/.env)9rB   rC   r   loggingrF   pathlibr   typingr   r   r   dataclassesr   hashlibr   rV   PILr   rr   googleapiclient.discoveryr   google.oauth2.credentialsr	   r   seleniumr
   !selenium.webdriver.chrome.optionsr   r  r   	getLoggerr>   rZ   StreamHandlerhandler	Formatter	formattersetFormatter
addHandlersetLevelINFOrM   r   r   r   r  r%  sysr'  botr1  r  argvjoinr  r7  printr=   r   r   <module>rT     s  
 
     ' ' ! 
/J
"9
 "8 "8 "8R 
		8	$



!TU	   Y    '   A AP> >J7 7|, ,f% %X/ /l z ^F
F
CNN
388}q"&&&u-&'-.hi q  H  E
C  E  IG  FsW   F+ 
F; G G G1 +	F87F8;G
	G
GGG.-G.1	G>=G>