ASP Classic blog framework - BrainOrdure
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

405 lignes
15KB

  1. <%
  2. Class AdminController_Class
  3. Private m_useLayout
  4. Private m_title
  5. Private Sub Class_Initialize()
  6. m_useLayout = True
  7. m_title = "Admin"
  8. End Sub
  9. Public Property Get useLayout
  10. useLayout = m_useLayout
  11. End Property
  12. Public Property Let useLayout(v)
  13. m_useLayout = v
  14. End Property
  15. Public Property Get Title
  16. Title = m_title
  17. End Property
  18. Public Property Let Title(v)
  19. m_title = v
  20. End Property
  21. '---------------------------------------------------------------
  22. ' Action: Index
  23. '---------------------------------------------------------------
  24. Public Sub Index()
  25. m_title = "Admin Dashboard"
  26. %>
  27. <!--#include file="../views/Admin/index.asp" -->
  28. <%
  29. End Sub
  30. '---------------------------------------------------------------
  31. ' Action: Posts
  32. '---------------------------------------------------------------
  33. Public Sub Posts()
  34. m_title = "Manage Posts"
  35. Dim posts
  36. Set posts = PostsRepository().FindAllWhere(Empty, "CreatedDate DESC", 0, 0)
  37. %>
  38. <!--#include file="../views/Admin/posts.asp" -->
  39. <%
  40. End Sub
  41. '---------------------------------------------------------------
  42. ' Action: Categories
  43. '---------------------------------------------------------------
  44. Public Sub Categories()
  45. m_title = "Manage Categories"
  46. Dim categories
  47. Set categories = CategoriesRepository().FindAll
  48. %>
  49. <!--#include file="../views/Admin/categories.asp" -->
  50. <%
  51. End Sub
  52. '---------------------------------------------------------------
  53. ' Action: Comments
  54. '---------------------------------------------------------------
  55. Public Sub Comments()
  56. m_title = "Manage Comments"
  57. Dim comments
  58. Set comments = CommentsRepository().Find(Empty, "CreatedDate")
  59. %>
  60. <!--#include file="../views/Admin/comments.asp" -->
  61. <%
  62. End Sub
  63. '---------------------------------------------------------------
  64. ' Action: AIPrompt
  65. '---------------------------------------------------------------
  66. Public Sub AIPrompt()
  67. m_title = "AI Prompt Settings"
  68. Dim promptTemplate : promptTemplate = GetGenerationPromptTemplate()
  69. %>
  70. <!--#include file="../views/Admin/ai-prompt.asp" -->
  71. <%
  72. End Sub
  73. '---------------------------------------------------------------
  74. ' Action: UpdateAIPrompt
  75. '---------------------------------------------------------------
  76. Public Sub UpdateAIPrompt()
  77. Dim promptTemplate : promptTemplate = Trim(Request.Form("PromptTemplate"))
  78. If Len(promptTemplate) = 0 Then
  79. Flash().AddError "Prompt template cannot be empty."
  80. Response.Redirect "/admin/ai-prompt"
  81. Exit Sub
  82. End If
  83. On Error Resume Next
  84. UpdateAppSetting "AbacusGenerationPrompt", promptTemplate
  85. If Err.Number <> 0 Then
  86. Flash().AddError "Unable to save prompt template: " & Err.Description
  87. Err.Clear
  88. On Error GoTo 0
  89. Response.Redirect "/admin/ai-prompt"
  90. Exit Sub
  91. End If
  92. On Error GoTo 0
  93. Flash().Success = "AI prompt template saved."
  94. Response.Redirect "/admin/ai-prompt"
  95. End Sub
  96. '---------------------------------------------------------------
  97. ' Action: PublishPost
  98. '---------------------------------------------------------------
  99. Public Sub PublishPost(ByVal id)
  100. Dim post
  101. On Error Resume Next
  102. Set post = PostsRepository().FindByID(id)
  103. If Err.Number <> 0 Then
  104. Err.Clear
  105. On Error GoTo 0
  106. Flash().AddError "Post not found."
  107. Response.Redirect "/admin/posts"
  108. Exit Sub
  109. End If
  110. On Error GoTo 0
  111. post.IsPublished = 1
  112. If Not IsDate(post.PublishedDate) Or CDate(post.PublishedDate) <= #1/1/1970# Then
  113. post.PublishedDate = Now()
  114. End If
  115. post.UpdatedDate = Now()
  116. PostsRepository().Update post
  117. Flash().Success = "Post published."
  118. Response.Redirect "/admin/posts"
  119. End Sub
  120. '---------------------------------------------------------------
  121. ' Action: UnpublishPost
  122. '---------------------------------------------------------------
  123. Public Sub UnpublishPost(ByVal id)
  124. Dim post
  125. On Error Resume Next
  126. Set post = PostsRepository().FindByID(id)
  127. If Err.Number <> 0 Then
  128. Err.Clear
  129. On Error GoTo 0
  130. Flash().AddError "Post not found."
  131. Response.Redirect "/admin/posts"
  132. Exit Sub
  133. End If
  134. On Error GoTo 0
  135. post.IsPublished = 0
  136. post.UpdatedDate = Now()
  137. PostsRepository().Update post
  138. Flash().Success = "Post unpublished."
  139. Response.Redirect "/admin/posts"
  140. End Sub
  141. '---------------------------------------------------------------
  142. ' Action: ApproveComment
  143. '---------------------------------------------------------------
  144. Public Sub ApproveComment(ByVal id)
  145. UpdateCommentApproval id, 1, "Comment approved."
  146. End Sub
  147. '---------------------------------------------------------------
  148. ' Action: UnapproveComment
  149. '---------------------------------------------------------------
  150. Public Sub UnapproveComment(ByVal id)
  151. UpdateCommentApproval id, 0, "Comment unapproved."
  152. End Sub
  153. '---------------------------------------------------------------
  154. ' Action: DeleteComment
  155. '---------------------------------------------------------------
  156. Public Sub DeleteComment(ByVal id)
  157. Dim comment
  158. On Error Resume Next
  159. Set comment = CommentsRepository().FindByID(id)
  160. If Err.Number <> 0 Then
  161. Err.Clear
  162. On Error GoTo 0
  163. Flash().AddError "Comment not found."
  164. Response.Redirect "/admin/comments"
  165. Exit Sub
  166. End If
  167. On Error GoTo 0
  168. CommentsRepository().Delete id
  169. Flash().Success = "Comment deleted."
  170. Response.Redirect "/admin/comments"
  171. End Sub
  172. '---------------------------------------------------------------
  173. ' Action: GenerateAIContent
  174. '---------------------------------------------------------------
  175. Public Sub GenerateAIContent(ByVal id)
  176. Dim post
  177. On Error Resume Next
  178. Set post = PostsRepository().FindByID(id)
  179. If Err.Number <> 0 Then
  180. Err.Clear
  181. On Error GoTo 0
  182. Flash().AddError "Post not found."
  183. Response.Redirect "/admin/posts"
  184. Exit Sub
  185. End If
  186. On Error GoTo 0
  187. Dim generatedSummary, generatedBody, generatedImagePrompt, generatedImageHtml
  188. On Error Resume Next
  189. GeneratePostContentFromAI post, generatedSummary, generatedBody, generatedImagePrompt
  190. If Err.Number <> 0 Then
  191. Flash().AddError "AI content generation failed: " & Err.Description
  192. Err.Clear
  193. On Error GoTo 0
  194. Response.Redirect PostEditUrl(post.PostID)
  195. Exit Sub
  196. End If
  197. On Error GoTo 0
  198. If Len(Trim(generatedSummary)) = 0 Or Len(Trim(generatedBody)) = 0 Then
  199. Flash().AddError "AI content generation returned empty content."
  200. Response.Redirect PostEditUrl(post.PostID)
  201. Exit Sub
  202. End If
  203. generatedImageHtml = BuildGeneratedImageHtml(generatedImagePrompt, post.Title, generatedSummary)
  204. post.Summary = generatedSummary
  205. post.Body = generatedImageHtml & generatedBody
  206. post.UpdatedDate = Now()
  207. PostsRepository().Update post
  208. Flash().Success = "AI content generated."
  209. Response.Redirect PostEditUrl(post.PostID)
  210. End Sub
  211. Private Sub GeneratePostContentFromAI(ByRef post, ByRef generatedSummary, ByRef generatedBody, ByRef generatedImagePrompt)
  212. Dim apiKey : apiKey = Trim(CStr(GetSecureSetting("AbacusApiKey", "ABACUS_API_KEY")))
  213. If Len(apiKey) = 0 Then
  214. Err.Raise 1, "AdminController.GeneratePostContentFromAI", "Abacus API key is not configured."
  215. End If
  216. Dim baseUrl : baseUrl = Trim(CStr(GetAppSetting("AbacusApiBaseUrl")))
  217. If Len(baseUrl) = 0 Or LCase(baseUrl) = "nothing" Then baseUrl = "https://routellm.abacus.ai/v1"
  218. If Right(baseUrl, 1) = "/" Then baseUrl = Left(baseUrl, Len(baseUrl) - 1)
  219. Dim modelName : modelName = Trim(CStr(GetAppSetting("AbacusModel")))
  220. If Len(modelName) = 0 Or LCase(modelName) = "nothing" Then modelName = "route-llm"
  221. Dim systemPrompt, userPrompt, payload, responseText, parsed, choices, choice, message, content, contentJson
  222. systemPrompt = "You write clear, engaging blog post content for a classic ASP blog. Return only valid JSON with three keys: summary, image_prompt, and body. Summary must be 1 to 2 sentences. image_prompt must be a concise visual description suitable for an AI image generator and should not mention markdown. Body must be 3 to 5 short paragraphs of HTML with simple semantic tags like p, strong, em, ul, ol, and h2. Do not use markdown fences or code blocks."
  223. userPrompt = BuildGenerationPrompt(post) & vbCrLf & vbCrLf & _
  224. "Also return an image_prompt field that describes a magazine-style feature image for this post."
  225. payload = "{""model"":""" & JsonEscape(modelName) & """,""messages"":[{""role"":""system"",""content"":""" & JsonEscape(systemPrompt) & """},{""role"":""user"",""content"":""" & JsonEscape(userPrompt) & """}],""temperature"":0.7}"
  226. responseText = HttpPostJson(baseUrl & "/chat/completions", apiKey, payload)
  227. Set parsed = json()
  228. parsed.loadJSON responseText
  229. If Not parsed.data.Exists("choices") Then
  230. Err.Raise 1, "AdminController.GeneratePostContentFromAI", "Abacus API response did not include choices."
  231. End If
  232. Set choices = parsed.data.Item("choices")
  233. If choices.Count = 0 Then
  234. Err.Raise 1, "AdminController.GeneratePostContentFromAI", "Abacus API returned no choices."
  235. End If
  236. Set choice = choices.Item(0)
  237. If Not choice.Exists("message") Then
  238. Err.Raise 1, "AdminController.GeneratePostContentFromAI", "Abacus API response did not include a message."
  239. End If
  240. Set message = choice.Item("message")
  241. If Not message.Exists("content") Then
  242. Err.Raise 1, "AdminController.GeneratePostContentFromAI", "Abacus API response did not include content."
  243. End If
  244. content = Trim(CStr(message.Item("content")))
  245. contentJson = ExtractJsonObject(content)
  246. Set parsed = json()
  247. parsed.loadJSON contentJson
  248. If parsed.data.Exists("summary") Then generatedSummary = Trim(CStr(parsed.data.Item("summary")))
  249. If parsed.data.Exists("body") Then generatedBody = Trim(CStr(parsed.data.Item("body")))
  250. If parsed.data.Exists("image_prompt") Then generatedImagePrompt = Trim(CStr(parsed.data.Item("image_prompt")))
  251. If Len(Trim(generatedImagePrompt)) = 0 And parsed.data.Exists("images") Then
  252. generatedImagePrompt = BuildImagePromptFromSuggestions(parsed.data.Item("images"))
  253. End If
  254. End Sub
  255. Private Sub UpdateCommentApproval(ByVal id, ByVal isApproved, ByVal successMessage)
  256. Dim comment
  257. On Error Resume Next
  258. Set comment = CommentsRepository().FindByID(id)
  259. If Err.Number <> 0 Then
  260. Err.Clear
  261. On Error GoTo 0
  262. Flash().AddError "Comment not found."
  263. Response.Redirect "/admin/comments"
  264. Exit Sub
  265. End If
  266. On Error GoTo 0
  267. comment.IsApproved = isApproved
  268. CommentsRepository().Update comment
  269. Flash().Success = successMessage
  270. Response.Redirect "/admin/comments"
  271. End Sub
  272. Private Function HttpPostJson(ByVal url, ByVal apiKey, ByVal payload)
  273. Dim http
  274. Set http = Server.CreateObject("Msxml2.ServerXMLHTTP.6.0")
  275. http.setTimeouts 10000, 10000, 10000, 30000
  276. http.open "POST", url, False
  277. http.setRequestHeader "Content-Type", "application/json"
  278. http.setRequestHeader "Authorization", "Bearer " & apiKey
  279. http.send payload
  280. If http.status < 200 Or http.status >= 300 Then
  281. Err.Raise IIf(http.status > 0, http.status, 1), "AdminController.HttpPostJson", "Abacus API returned HTTP " & http.status & ": " & Left(CStr(http.responseText), 500)
  282. End If
  283. HttpPostJson = http.responseText
  284. End Function
  285. Private Function BuildGeneratedImageHtml(ByVal imagePrompt, ByVal titleText, ByVal summaryText)
  286. Dim promptText, altText, imageUrl
  287. promptText = Trim(CStr(imagePrompt))
  288. If Len(promptText) = 0 Then
  289. BuildGeneratedImageHtml = ""
  290. Exit Function
  291. End If
  292. altText = Trim(CStr(summaryText))
  293. If Len(altText) = 0 Then altText = Trim(CStr(titleText))
  294. If Len(altText) = 0 Then altText = "Feature image"
  295. imageUrl = GetOrCreateAiImageUrl(promptText)
  296. BuildGeneratedImageHtml = "<figure class=""post-feature-image mb-4"">" & _
  297. "<img class=""img-fluid rounded-4"" src=""" & Server.HTMLEncode(imageUrl) & """ alt=""" & Server.HTMLEncode(altText) & """ />" & _
  298. "</figure>"
  299. End Function
  300. Private Function BuildImagePromptFromSuggestions(ByVal imagesData)
  301. Dim key, imageItem, textParts, part, candidate
  302. candidate = ""
  303. On Error Resume Next
  304. If TypeName(imagesData) = "Dictionary" Then
  305. For Each key In imagesData.Keys
  306. Set imageItem = imagesData.Item(key)
  307. candidate = ""
  308. If TypeName(imageItem) = "Dictionary" Then
  309. If imageItem.Exists("search_query") Then candidate = Trim(CStr(imageItem.Item("search_query")))
  310. If Len(candidate) = 0 And imageItem.Exists("caption") Then candidate = Trim(CStr(imageItem.Item("caption")))
  311. If Len(candidate) = 0 And imageItem.Exists("alt_text") Then candidate = Trim(CStr(imageItem.Item("alt_text")))
  312. If Len(candidate) > 0 Then Exit For
  313. Else
  314. candidate = Trim(CStr(imageItem))
  315. If Len(candidate) > 0 Then Exit For
  316. End If
  317. Next
  318. Else
  319. candidate = Trim(CStr(imagesData))
  320. End If
  321. On Error GoTo 0
  322. If Len(candidate) = 0 Then
  323. BuildImagePromptFromSuggestions = ""
  324. Else
  325. BuildImagePromptFromSuggestions = candidate
  326. End If
  327. End Function
  328. Private Function ExtractJsonObject(ByVal text)
  329. Dim startPos, endPos
  330. startPos = InStr(text, "{")
  331. endPos = InStrRev(text, "}")
  332. If startPos > 0 And endPos > startPos Then
  333. ExtractJsonObject = Mid(text, startPos, endPos - startPos + 1)
  334. Else
  335. ExtractJsonObject = text
  336. End If
  337. End Function
  338. End Class
  339. Dim AdminController_Class__Singleton
  340. Function AdminController()
  341. If IsEmpty(AdminController_Class__Singleton) Then
  342. Set AdminController_Class__Singleton = New AdminController_Class
  343. End If
  344. Set AdminController = AdminController_Class__Singleton
  345. End Function
  346. %>

Powered by TurnKey Linux.