
    [hW              $          d dl  ej                  dej                         eej                        fdedede	fd       Z
ej                  dej                         ed	d
d       ed	       ed	       ed	       ed	       ed	       ed	       ed	       ed       eej                        f
dededededededededee   de	fd       Zej                  dej                         edd
d       ed       ed       ed       ed       ed       ed       ed       ed       ed       ed       ed       ed       ed       ed       eej                        fdedee   dee   dee   dee   dee   dee   dee   dee   dee   dee   dee   dee   dee   dee   dee   de	f"d       Zej                  d       defd!       Zej                  d"      defd#       Zej                  d$ej                        d%d  eej                        fded&ed'ede	fd(       Zej                  d)ej                         eej                        fdede	fd*       Zej+                  d+ej                         eej                        fdede	fd,       Zej                  d-ej                         eej                        fded.ede	fd/       Zej1                  e      d0ed1efd2       Zej1                  e      d1efd3       ZdFd4ed5efd6Zd7efd8Zd9ed:ed;efd<Z dGd=ed>efd?Z!dHd@edAefdBZ"dCededDefdEZ#y)I    )*z/generate-article)response_modeltopicemaildbc           
      Z  K   t         j                  d       dt        j                          }|st	        d      S t
        j                  t        |      s,t        t        j                  t        j                  dd      S | st	        d      S t        |       dkD  rt	        d	      S t        |       d
k  rt	        d      S | j                         st	        d      S t        j                  |       }t        | j!                  dd      j!                  dd            }|}t         j"                  j%                  t&        |      }t         j"                  j%                  |t(              }t         j+                  |d       t         j"                  j%                  || d      }	t-        | |	      }
t.         d|  }t1        || |d|t2        j5                         t2        j5                               }|j7                  |       |j9                          |j;                  |       d|  d}d| d| d}t=        |||       d{    t>        j@                  jC                  |      jE                         }tG        |      }t        t        jH                  t        jH                  d|d      S 7 iw)N
    Generate a STORM article and return it as a downloadable IMSCC file.
    COURSE_PREFIX-Email is requiredEmail: Invalid value.statusmessagestatus_codecontentTopic is requiredd   4Topic is too long. Maximum length is 100 characters.   3Topic is too short. Minimum length is 5 characters.$Topic contains non-ASCII characters. _/Texist_ok.imsccoutput_pathz/download-imscc?topic=Ready)	course_idr   r   r   course_imscc_url
created_at
updated_atYour topic  is ready to downloadcDear User,<br/><p>Please find the below link to download imscc file.</p><p>Download Link: <a href='' target='_blank'>4</a></p><p></p><br/>Warm Regards,<br/>Answerous TeamNData retrieved successfullyr   r   data)%osgetenvuuiduuid4errorResponserematchEMAIL_REGEXJSONResponser   HTTP_400_BAD_REQUESTlenisasciirunnerruntruncate_filenamereplacepathjoinworking_dircontent_dirmakedirsgenerate_imsccAPP_URLCoursesdatetimeutcnowaddcommitrefresh
send_emailschemasCoursesResponsefrom_ormdictjsonable_encoderHTTP_200_OK)r   r   r   r#   resultarticle_title	file_patharticle_dirwiki_content_dirimscc_file_nameimscc_file_pathdownload_link
new_coursesubjectmail_contentcourse_dataencoded_datas                    /var/www/html/sandstorm/main.pygeneratera      s    
 IIo./q?I
 	
 88K'33 552
 	
 
 	
 5zCB
 	
 5zA~A
 	
 ==?2
 	
 ZZF &MM#s#++C5
M I'',,{M:Kww||K=KK 4K0ggll9v.FGO
 %UHOi5eW=M,!*!*
J FF:IIKJJzE7"78Gx  zG  yH  HZ  [h  Zi  i]  ^L
U7<
000))22:>CCEK#K0L&&((4 
  1s   H=J+?J) A*J+z/create-a-course.r   r   )
min_length
max_lengthNskill_developmenteducation_degreeallocated_timelanguagemode_of_deliverytoneweblinksc
                 f  K   t         j                  d       dt        j                          }
|st	        d      S t
        j                  t        |      s,t        t        j                  t        j                  dd      S | st	        d      S t        |       dkD  rt	        d	      S t        |       d
k  rt	        d      S | j                         st	        d      S |rS	 |j                  d      D cg c]#  }|j                         s|j                         % }}t        j!                  |      }d}t%        |
| ||||||||r|nddd|t&        j)                         t&        j)                               }|	j+                  |       |	j-                          |	j/                  |       d|  d}d| d| d}|r(	 t        j1                  |      }dj3                  |      }nd}t4        j6                  j9                  |      j;                         }||d<   t=        |      }t        t        j>                  t        j>                  d|d      S c c}w # t        j"                  $ r/ t        t        j                  t        j                  dd      cY S w xY w# t        j"                  $ r |}Y w xY ww)r	   r
   r   r   r   r   r   r   r   r   r   r   r   ,Weblinks: Invalid JSON format. NPending   )r#   r   r   rd   re   rf   rg   rh   ri   rj   r   course_stepr$   r%   r&   r'   r(   r)   r*   r+   , rj   r,   r-   ) r/   r0   r1   r2   r3   r4   r5   r6   r7   r   r8   r9   r:   splitstripjsondumpsJSONDecodeErrorrF   rG   rH   rI   rJ   rK   loadsr@   rM   rN   rO   rP   rQ   rR   )r   r   rd   re   rf   rg   rh   ri   rj   r   r#   urlrZ   r[   r\   r]   weblink_listweblink_csvr^   r_   s                       r`   createCourser|   \   s      IIo./q?I
 	
 88K'33 552
 	
 
 	
 5zCB
 	
 5zA~A
 	
 ==?2
 	
 
	/7~~c/BRciik		RHRzz(+H  M 1/+/#+x,!*!*!
J$ FF:IIKJJzE7"78Gx  zG  yH  HZ  [h  Zi  i]  ^L 	#::h/L))L1K ))22:>CCEK)K
#K0L&&((4 
 y S## 	"77$99? 	b ## 	#"K	#sh   CJ1I 2III 1BJ19&J A-J1I ?JJ1JJ1J.+J1-J..J1z/update-course/{course_id}r#   content_descriptioncontent_outcomescontent_objectivescontent_outlinelearning_approachno_of_modulesrq   c           	      R  K   |j                  t              j                  t        j                  | k(        j	                         }|st        d      S |rTt        |      dkD  rt        d      S t        |      dk  rt        d      S |j                         st        d      S ||_        |rMt        j                  t        |      s,t        t        j                  t        j                  dd	      S ||_        |r||_        |r||_        |r||_        |r||_        |r||_        |r||_        |	r|	|_        |
r|
|_        |r||_        |r||_        |||_        |rX	 |j7                  d      D cg c]#  }|j9                         s|j9                         % }}t:        j=                  |      |_        |8|dk  r,t        t        j                  t        j                  dd	      S ||_!        |jE                          |jG                  |       |j>                  r2	 t:        jI                  |j>                        }djK                  |      }nd
}tL        jN                  jQ                  |      jS                         }||d<   t        t        jT                  tW        t        jT                  d|d      	      S c c}w # t:        j@                  $ r/ t        t        j                  t        j                  dd	      cY S w xY w# t:        j@                  $ r |j>                  }Y w xY ww)z,
    Update course details by course_id
    Course not foundr   r   r   r   r   r   r   r   Nrl   rm   rp   zCourse step must be at least 1.rr   rj   zCourse updated successfullyr-   ),queryrF   filterr#   firstr3   r9   r:   r   r4   r5   r6   r7   r   r8   r   rd   re   rf   rh   ri   r}   r~   r   r   r   r   rs   rt   ru   rv   rj   rw   rq   rJ   rK   rx   r@   rM   rN   rO   rP   rR   rQ   )r#   r   r   rd   re   rf   rh   ri   r}   r~   r   r   r   r   rj   rq   r   coursery   rz   r{   response_datas                         r`   updateCourser      s    0 XXg%%g&7&79&DEKKMF
 	
 u: F  u:> E  }} 6  xxU+"77$996  #4 "2 ."2%8""2$6!!0#4  ,
	/7~~c/BRciik		RHR"jj2FO ?"77$99@  )IIKJJv	*::foo6L))L1K ++44V<AACM +M*&& ((4!"
  K S## 	"77$99? 	6 ## 	* //K	*sh   EL'J= 1J8J8J= 5A'L'0L A+L'8J= =?K?<L'>K??L'L$!L'#L$$L'z/download-imsccc                    t        | j                  dd      j                  dd            }t        j                  j	                  t
        |      }| d}t        j                  j	                  t
        |      }t        j                  j	                  |d      }t        j                  j	                  t        |      }t        j                  j	                  |t              }t        ||       t        j                  j                  |      st        dd      t        || |       t        | |	      }t        |d
|      S )r	   r   r   r   r   storm_gen_article_polished.txti  z5Article not found. Please generate the article first.)r   detailr    zapplication/zip)
media_typefilename)r=   r>   r/   r?   r@   OUTPUT_FOLDERrA   rB   save_sections_as_htmlexistsHTTPExceptionprepare_article_questionrD   FileResponse)r   rT   rU   r   imscc_filepathpolished_article_pathrV   
imscc_paths           r`   download_imsccr   R  s    
 &MM#s#++C5
M ]M:I'HWW\\-:NGGLL4TU'',,{M:K'',,{K8K /=77>>/04kll2E;G>BJ $     z/generate-quizc                    t        | j                  dd      j                  dd            }t        j                  j	                  t
        |      }t        j                  j	                  |d      }t        |      }t        |      }| |dS )z?
    Generate quiz questions based on the article content.
    r   r   r   r   )r   	questions)r=   r>   r/   r?   r@   r   read_txt_filegenerate_questions_from_article)r   rT   rU   r   article_contentr   s         r`   generate_quizr   s  su     &MM#s#++C5
M ]M:IGGLL4TU#$9:O/@I33r   z/course-list
   limitoffsetc           
         |j                  t              j                  t        j                  | k(        }|j	                         }|j                  |      j                  |      j                         }|st        dg       S |D cg c]!  }t        j                  j                  |      # }}t        |      }	t        t        j                  t        j                  d|	|||d      S c c}w )zB
    Get list of all courses with pagination (limit & offset)
    zNo courses foundr,   )r   r   r.   totalr   r   r   )r   rF   r   r   countr   r   allsuccessResponserM   rN   rO   rQ   r7   r   rR   )
r   r   r   r   courses_queryr   coursesr   r^   r_   s
             r`   get_course_listr     s     HHW%,,W]]e-CDM!E""6*007;;=G
 	
 KRR7**33F;RKR#K0L&&((4 

 
 Ss   &C)z/course/{course_id}c                 ~   |j                  t              j                  t        j                  | k(        j	                         }|st        dg       S t        |j                  j                  dd      j                  dd            }t        j                  j                  t        |      }t        j                  j                  |d      }t        |      }i t        t        j                   j#                  |      j%                               d|i}t'        t(        j*                  t(        j*                  d|d	      S )
z)
    Get course details by course_id
    r   r   r   r   r   course_contentr,   r-   r   )r   rF   r   r#   r   r   r=   r   r>   r/   r?   r@   r   r   rQ   rM   rN   rO   rP   r7   r   rR   )r#   r   r   rT   rU   r   r   r   s           r`   
get_courser     s   
 XXg%%g&7&79&DEKKMF
 	
 &LL  c*223<
M ]M:IGGLL4TU#$9:O
722;;FCHHJ
K/M
 &&((4!
 r   z/course/delete/{course_id}c                    |j                  t              j                  t        j                  | k(        j	                         }|st        d      S |j                  |       |j                          t        t        j                  t        j                  dt        j                  j                  |      j                         d      S )z$
    Delete course by course_id
    r   zCourse deleted successfullyr-   r   )r   rF   r   r#   r   r3   deleterJ   r7   r   rR   rM   rN   rO   rP   )r#   r   r   s      r`   delete_courser     s    
 XXg%%g&7&79&DEKKMF
 	
 IIfIIK&&((4++44V<AAC
 r   z$/course/{course_id}/citation/{index}indexc                    |j                  t              j                  t        j                  | k(        j	                         }|st        d      S t        |j                  j                  dd      j                  dd            }t        j                  j                  t        |      }t        j                  j                  |d      }t        |      }t        ||      }t        t         j"                  t         j"                  d|d      S )	z*
    Get course citation by course_id
    r   r   r   r   zurl_to_info.jsonr,   r-   r   )r   rF   r   r#   r   r3   r=   r   r>   r/   r?   r@   r   read_json_file$construct_citation_dict_from_articler7   r   rR   )	r#   r   r   r   rT   rU   r   r   citation_dicts	            r`   get_course_citationr     s    
 XXg%%g&7&79&DEKKMF
 	
 &LL  c*223<
M ]M:IGGLL4FG$%:;O8%PM &&((4!
 r   requestexcc                    K   |j                         D cg c]'  }dj                  d |d   D              |d   |d   d) }}t        dd|d   d	   |d   d
   d      S c c}w w)N.c              3   2   K   | ]  }t        |        y w)N)str).0locs     r`   	<genexpr>z6custom_validation_exception_handler.<locals>.<genexpr>  s     ?3c#h?s   r   msgtype)fieldr   r   i  r   r   r   )r   r   r   r   )errorsr@   r7   )r   r   errorr   s       r`   #custom_validation_exception_handlerr     s      ZZ\ 	 XX?%,??U|&M	
F  ay+AYw'
 s   A%,A $A%c                    K   |j                   dk(  r|j                  dk(  rt        dddd      S t        |j                   |j                   |j                  d      S w)Ni  zNot authenticatedi  zMissing API Tokenr   r   )r   r   r7   )r   r   s     r`   custom_http_exception_handlerr   
  s]     
##**0C"C"/BC
 	
 OO??szzB s   AArT   r!   c           	         t        | j                  dd      j                  dd            }t        j                  j	                  t
        |      }t        j                  t
        d       t        j                  |d       t        | t        j                  j	                  |t              t        t        j                  j	                  |d             t        j                  |dt        j                        5 }t        j                  |      D ]`  \  }}}|D ]U  }t        j                  j	                  ||      }	t        j                  j                  |	|	      }
|j                  |	|
       W b 	 d
d
d
       |S # 1 sw Y   |S xY w)zE
        Generate an IMSCC package from the article content.
        r   r   r   Tr   zimsmanifest.xml)course_titlerB   wiki_diroutput_filew)startN)r=   r>   r/   r?   r@   rA   rC   create_manifestrB   zipfileZipFileZIP_DEFLATEDwalkrelpathwrite)rT   r!   sanitized_stringrW   zfrootr   filesfile	full_patharcnames              r`   rD   rD     s=   
 -!!#s+33C=
 77<<5EF
K$/
$t4 	&%5{C %57HI		
 __[#w/C/CD 	1"$''*:"; 1a! 1D "T4 8I ggooi?OoPGHHY011	1 	1 s   :A9E>>Fmd_textc                     t         j                  d| t         j                        }|D cg c]#  }|j                         s|j                         % c}S c c}w )zBSplits the markdown into sections based on top-level (#) headings.z	(?=^# .+))flags)r4   rs   	MULTILINErt   )r   sectionsss      r`   split_markdown_sectionsr   8  s<    xxgR\\xBH'5!1779AGGI555s   AAtitler   returnc                 F    t         j                  |g d      }d|  d| dS )N)extra
codehilitetablestoc)
extensionsz@<html>
    <head>
        <meta charset="utf-8">
        <title>z(</title>
    </head>
    <body>
        z
    </body>
    </html>
    )markdown)r   r   	body_htmls      r`   markdown_to_htmlr   =  s?    !!'6^!_I w 	 
 	 	r   md_path
output_dirc                 
   t         j                  |d       t        |       }t        |      }|D ]  }|j	                         }|d   j                  d      j                         }|j                         j                  dd       d}t        ||      }t         j                  j                  ||      }	t        |	dd	
      5 }
|
j                  |       ddd        t        dt        |       d|        y# 1 sw Y   xY w)za
    Reads a markdown file, splits it into sections, and saves each section as an HTML file.
    Tr   r   z# r   r   .htmlr   utf-8encodingNu   ✅ Exported z sections to: )r/   rC   r   r   
splitlinesrt   lowerr>   r   r?   r@   openr   printr9   )r   r   r   r   sectionlines
title_liner   htmlr!   outs              r`   r   r   J  s     KK
TK* G$G&w/H 	""$1X^^D)//1
 &&(00c:;5A
G4ggll:x8+sW5 	IIdO	 		 
M#h-zl
CD	 	s   C99D	article_textnum_questionsc                     d| d|  d}t               }|j                  j                  j                  dd|dgd      }|j                  d	   j
                  j                  S )
Nz+
    Given the following article, generate aT   quiz questions including:
    - Descriptive
    - Multiple choice (with 4 options)
    - Single choice
    - Fill in the blank
    - Optional (True/False)

    Format each question like:
    Type: <type>
    Question: <text>
    Options: <A, B, C, D> (only if applicable)
    Answer: <correct or expected answer>

    Article:
    """
    z
    """
    zgpt-4user)roler   gffffff?)modelmessagestemperaturer   )OpenAIchatcompletionscreatechoicesr   r   )r   r   promptopenai_clientresponses        r`   r   r   d  s~    ++8/ : N !F& (M!!--44!f56 5 H A&&...r   r   rV   c                    t        |       }t        |      }t        |j                  dd      j                  dd            }d|j	                         j                  dd       d}t        ||      }t        j                  j                  ||      }t        |dd      5 }	|	j                  |       d	d	d	       y	# 1 sw Y   y	xY w)
zK
    Read the polished article content and generate questions from it.
    r   r   r   
questions_r   r   r   r   N)r   r   r=   r>   r   r   r/   r?   r@   r   r   )
r   r   rV   r   r   rT   question_filenamer   r!   r   s
             r`   r   r     s     $$9:O/@I%MM#s#++C5
M %]%8%8%:%B%B3%L$MUSM95D'',,{,=>K	k3	1 S		$  s    B;;C)zoutput.imscc)wiki_content)r   )$dependencies.hubappgetrM   rN   Dependsr   get_dbr   Sessionra   postFormOptionalr|   intr   r   r   r   r   r   r   r   exception_handlerRequestValidationErrorRequestr   r   r   rD   r   r   r   r   r    r   r`   <module>r!     s,    	W-D-DE9@9K T# Tc Tw T FTl 
W-D-DEcaC8c!#Y IcI IS	"4j"))$ttt t 	t
 t t t t smt 	t Ftl 
&w7N7NO  sC:'+Dz&*4j$(J&*4jt*)-d&*4j(,T
%)$Z'+Dz#':"4j!%d"))$#{{C={ C={  }	{
 sm{ SM{ sm{ 3-{ "#{ sm{ !{ c]{  }{ C={ sm{  #!{" 	#{ P{| 	#  @ 	4 4 4 (?(?@ "))$	      		  A B 	w/F/FG-4RYY-? # 7  H< (9P9PQ07		0B S g  R& 	/@W@WXBI"))BT 3 s   Y: -.w E[  /& }%	m 	 &	# C D6S 6
C # # E3 EC E4/# /c /:C  QT r   