Skip to content

Commit cb099f5

Browse files
jnilesaths008
authored andcommitted
Update shared
1 parent ed462ba commit cb099f5

4 files changed

Lines changed: 370 additions & 112 deletions

File tree

api/impl.go

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
package api
22

33
import (
4+
"context"
45
"encoding/json"
56
"errors"
7+
"fmt"
68
"net/http"
9+
"os"
10+
"strings"
711

812
"go.uber.org/zap"
913
)
@@ -52,3 +56,165 @@ func (s Server) GetAPIHealthcheck(w http.ResponseWriter, r *http.Request) {
5256
return
5357
}
5458
}
59+
60+
func (s Server) GetFunctionsIsWebsiteAIGenerated(w http.ResponseWriter, _ *http.Request) {
61+
d := Documentation{
62+
Name: "isWebsiteAIGenerated",
63+
Description: "Check if a website's content is AI generated",
64+
Input: struct {
65+
Description string `json:"description"`
66+
Example string `json:"example"`
67+
Type string `json:"type"`
68+
}{
69+
Description: "Website URL content to scan and check if it was AI generated.",
70+
Example: "https://saath.dev",
71+
Type: "string",
72+
},
73+
Output: struct {
74+
Description string `json:"description"`
75+
Example string `json:"example"`
76+
Type string `json:"type"`
77+
}{
78+
Description: "Information about the website provided and various scores",
79+
Example: `{
80+
"status": 200,
81+
"length": 1549,
82+
"score": 99.96,
83+
"sentences": [
84+
{
85+
"length": 171,
86+
"score": 99.08,
87+
"text": "\"Hello, I'm Saath Satheeshkumar. I'm a software developer with 4 years of experience.
88+
\\nAbout me\\nI am a fourth-year MSci Computer Science student at King's College London."
89+
},
90+
{
91+
"length": 541,
92+
"score": 100,
93+
"text": "I am a software engineer who is mainly interested in backend and low level systems.
94+
\\n\\nMy projects\\nMy skills\\n- AWS\\n- Java\\n- JavaScript/TypeScript\
95+
\n- Python\\n- Rust\\n- C++\\n- Golang\\n- Docker\\n- React\\n- Node.js\\n
96+
- Git\\n- PostgreSQL\\n- MariaDB\\nMy Experience\\nStarted MSci Computer Science Course
97+
\\nLondon, UK\\n\\nI started my undergraduate course in Computer Science at King's College London.
98+
\\n\\n2021Software Developer, Stealth Startup\\nLondon, UK\\n\\n
99+
I worked as a full-stack developer at a stealth startup which was focused on AI systems."
100+
},
101+
{
102+
"length": 451,
103+
"score": 100,
104+
"text": "I used Next.js, TypeScript, OpenAI's API, Tailwind and PostgreSQL.\\n
105+
\\n2023CTO, Denr\\nLondon, UK\\n\\n
106+
I'm now leading the development of Denr's peer-to-peer lending platform
107+
through a mobile application and website.\\n\\nAug 2023 - Jan 2024Software Engineer,
108+
Denr\\nLondon, UK\\n\\n
109+
I created the real-time notification service with Kafka and Golang,
110+
set up the database schema, created several controllers and was in charge of reviewing/approving backend PRs."
111+
},
112+
{
113+
"length": 383,
114+
"score": 99.95,
115+
"text": "Also created the internal dashboard with PHP's Laravel framework.
116+
\\n\\nMay 2024 - June 2024Software Engineeer Intern,
117+
Netcraft\\nLondon, UK\\n\\nJune 2024 - Oct 2024Software Engineeer Contract,
118+
Peterborough Council\\nLondon, UK\\n\\nImproving Peterborough's scheduling,
119+
sponsored by AWS\\n\\nSept 2024 - PresentContact me\\n
120+
Please contact me directly at saath@saath.dev or through this form.\\n\""
121+
}
122+
],
123+
"input": "website",
124+
"attack_detected": {
125+
"zero_width_space": false,
126+
"homoglyph_attack": false
127+
},
128+
"readability_score": 33.76,
129+
"credits_used": 193,
130+
"credits_remaining": 2307,
131+
"version": "4.1",
132+
"language": "en"
133+
}"`,
134+
Type: "object",
135+
},
136+
}
137+
138+
SetHeaderAndWriteResponse(w, http.StatusOK, d)
139+
}
140+
141+
type WinstonAIResp struct {
142+
Status int `json:"status"`
143+
Length int `json:"length"`
144+
Score float64 `json:"score"`
145+
Sentences []Sentence `json:"sentences"`
146+
Input string `json:"input"`
147+
AttackDetected Attack `json:"attack_detected"`
148+
ReadabilityScore float64 `json:"readability_score"`
149+
CreditsUsed int `json:"credits_used"`
150+
CreditsRemaining int `json:"credits_remaining"`
151+
Version string `json:"version"`
152+
Language string `json:"language"`
153+
}
154+
155+
type Sentence struct {
156+
Length int `json:"length"`
157+
Score float64 `json:"score"`
158+
Text string `json:"text"`
159+
}
160+
161+
type Attack struct {
162+
ZeroWidthSpace bool `json:"zero_width_space"`
163+
HomoglyphAttack bool `json:"homoglyph_attack"`
164+
}
165+
166+
func (s Server) PostFunctionsIsWebsiteAIGenerated(w http.ResponseWriter, r *http.Request) {
167+
var err error
168+
var body PostFunctionsIsWebsiteAIGeneratedJSONBody
169+
if err = json.NewDecoder(r.Body).Decode(&body); err != nil {
170+
s.Logger.Error(ErrUnmarshalBody, zap.Error(err))
171+
sendError(w, http.StatusBadRequest, ErrUnmarshalBody.Error())
172+
return
173+
}
174+
175+
winstonAIKey, present := os.LookupEnv("WINSTON_AI")
176+
if !present {
177+
s.Logger.Error("failed to get winston AI API key", zap.Error(err))
178+
sendError(w, http.StatusBadRequest, ErrUnmarshalBody.Error())
179+
return
180+
}
181+
182+
url := "https://api.gowinston.ai/v2/ai-content-detection"
183+
184+
winstonParams := fmt.Sprintf("{\n \"website\": \"%s\"\n}", body.Input)
185+
payload := strings.NewReader(winstonParams)
186+
187+
var req *http.Request
188+
if req, err = http.NewRequestWithContext(context.Background(), http.MethodPost, url, payload); err != nil {
189+
s.Logger.Error(ErrUnmarshalBody, zap.Error(err))
190+
sendError(w, http.StatusBadGateway, "failed to create http request to winston AI")
191+
return
192+
}
193+
194+
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", winstonAIKey))
195+
req.Header.Add("Content-Type", "application/json")
196+
197+
var winstonRes *http.Response
198+
if winstonRes, err = http.DefaultClient.Do(req); err != nil {
199+
s.Logger.Error(ErrUnmarshalBody, zap.Error(err))
200+
sendError(w, http.StatusBadGateway, "failed to send http request to winston AI")
201+
return
202+
}
203+
204+
defer winstonRes.Body.Close()
205+
206+
var winstonBody WinstonAIResp
207+
if err = json.NewDecoder(winstonRes.Body).Decode(&winstonBody); err != nil {
208+
s.Logger.Error(ErrUnmarshalBody, zap.Error(err))
209+
sendError(w, http.StatusBadGateway, ErrUnmarshalBody.Error())
210+
return
211+
}
212+
213+
resp := struct {
214+
Output WinstonAIResp `json:"output"`
215+
}{
216+
Output: winstonBody,
217+
}
218+
219+
SetHeaderAndWriteResponse(w, http.StatusOK, resp)
220+
}

api/middleware.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@ type RequestIDCtxKey struct{}
3535
func AuthMiddleware(next http.Handler) http.Handler {
3636
// Paths to ignore this
3737
excludedPaths := map[string]bool{
38-
"/api/auth/callback": true, // http cookie is not set before logging in ie. during OAuth flow
39-
"/api/healthcheck": true, // http cookie doesn't need to present for a healthcheck
38+
"/api/auth/callback": true, // http cookie is not set before logging in ie. during OAuth flow
39+
"/api/healthcheck": true, // http cookie doesn't need to present for a healthcheck
40+
"/functions/isWebsiteAIGenerated": true, // http cookie doesn't need to present for a healthcheck
4041
}
4142

4243
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -99,10 +100,11 @@ func RequestIDMiddleware(next http.Handler) http.Handler {
99100
// JWTMiddleware parses and validates the access token, and stores the userID in the request context.
100101
func JWTMiddleware(next http.Handler) http.Handler {
101102
excludedPaths := map[string]bool{
102-
"/api/auth/callback": true,
103-
"/api/healthcheck": true,
104-
"/api/users/logout": true,
105-
"/api/refresh": true,
103+
"/api/auth/callback": true,
104+
"/api/healthcheck": true,
105+
"/api/users/logout": true,
106+
"/api/refresh": true,
107+
"/functions/isWebsiteAIGenerated": true,
106108
}
107109

108110
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

0 commit comments

Comments
 (0)