Recent posts

#41
15 Sep: DEVASTATING BATTLE! Russian 72nd Brigade CEASES TO EXIST.

#42
Ukraine War: Russia's Black Sea ships will take 'very long time to repair'

#43
Looks like the total victory of Ukraine has been moved in time a bit.

Altogether, they have managed to conquer 0.3% of the originally Russian-occupied territory in 3 months using all the newest NATO weapons in their "Greatest Counter Offensive of all times".

Continuing at this speed, they will have freed their territory in approximately 83.33 years.

To put it in perspective, if we start counting from today, which is September 16, 2023, the territory would be fully reclaimed around the year 2107.






#44
Purebasic Tipps / Levenshtein Distance and "find...
Last post by Theo Gottwald - September 16, 2023, 05:02:03 AM
🌟 FindBestMatch Subprogram: Your Voice-Activated Command Center 🌟

📝 Description
The FindBestMatch subprogram is a powerful tool designed to find the best match for a given string within a list of strings. It uses the Levenshtein distance algorithm for string comparison, ensuring high accuracy. This is particularly useful when you're working with voice commands recognized by Whisper. The subprogram returns the number corresponding to the best match, making it easier to trigger specific actions or commands in your project. 🎯

📋 Parameters
U01: This is a comma or semicolon-separated list of strings. Each string can optionally start with a numeric value between 0 and 9999, followed by either a . or a - and any number of spaces. The numeric value can be missing. 📊

U02: This is the string you want to compare against all the cleaned-up elements in U01. 📝

📤 Returns
The subprogram returns the number corresponding to the best match in the list. If an error occurs, it returns -1. 🚀

📚 Important Variables
Ele(): This array holds the split elements from U01. 📦

Numbers(): This array holds the numbers associated with each element. 🔢

Element: This is an individual element from the list. 📜

CleanElement: This is the element after removing the numeric value, ".", "-", and spaces. 🧹

Number: This is the numeric value in front of each element, if present. 🎰

MinDistance: This is the minimum Levenshtein distance found so far. 📏

CurrentDistance: This is the Levenshtein distance for the current element. 📐

BestMatchNumber: This is the number corresponding to the best match. 🏆

ErrorCode: This is the error code for handling invalid inputs. ⚠️

🛠 Code Structure
The subprogram starts by initializing key variables like MinDistance, BestMatchNumber, and ErrorCode. It then proceeds to split the elements from U01 and store them in the Ele() array. The Levenshtein distance algorithm is applied to find the best match, and the corresponding number is returned.

🤔 Did You Notice?
If you're thinking, "Hey, this coding style looks like it's from ChatGPT," you're absolutely right! 🕵��♀️

🎉 Conclusion
The FindBestMatch subprogram is an invaluable tool for making your projects smarter and more interactive. Whether you're using voice commands or text-based inputs, this subprogram ensures that the most relevant action is triggered. 🌈

Happy Coding! 🎉👩�💻👨�💻

;--------------------------------------------------------------------
;           
;--------------------------------------------------------------------

ProcedureDLL.l LevenshteinDistance(string1.s, string2.s)
  Protected length1.l
  Protected length2.l 
  Protected i.l, j.l
 
  length1 = Len(string1)
  length2 = Len(string2)
 
  Dim matrix.l(length1, length2)
 
  For i = 0 To length1
    matrix(i, 0) = i
  Next i
 
  For j = 0 To length2
    matrix(0, j) = j
  Next j
 
  For j = 1 To length2
    For i = 1 To length1
      If Mid(string1, i, 1) = Mid(string2, j, 1)
        matrix(i, j) = matrix(i-1, j-1)
      Else
        matrix(i, j) = Min3(matrix(i-1, j) + 1, matrix(i, j-1) + 1, matrix(i-1, j-1) + 1)
      EndIf
    Next i
  Next j
  i=matrix(length1, length2)
  ProcedureReturn i
EndProcedure

;--------------------------------------------------------------------
; ----------------------------------------------------------------------------
; Procedure: FindBestMatch
; Description: Finds the best match for a given string in a list of strings.
;              Uses Levenshtein distance for string comparison.
;
; Parameters:
;  U01 - Comma or semicolon-separated list of strings. Each string can optionally
;        start with a numeric value between 0 and 9999, followed by either a "."
;        or a "-" and any number of spaces. The numeric value can be missing.
;  U02 - String to compare against all the cleaned-up elements in U01.
;
; Returns:
;  Number corresponding to the best match in the list. Returns -1 if an error occurs.
;
; Important Variables:
;  Ele() - Array to hold the split elements from U01.
;  Numbers() - Array to hold the numbers associated with each element.
;  Element - Individual element from the list.
;  CleanElement - Element after removing numeric value, ".", "-", and spaces.
;  Number - Numeric value in front of each element, if present.
;  MinDistance - Minimum Levenshtein distance found so far.
;  CurrentDistance - Levenshtein distance for the current element.
;  BestMatchNumber - Number corresponding to the best match.
;  ErrorCode - Error code for handling invalid inputs.
; ----------------------------------------------------------------------------

ProcedureDLL.l FindBestMatch(U01.s, U02.s)
  Protected Element.s, CleanElement.s, Number.s, Temp.s
  Protected MinDistance.i, CurrentDistance.i, BestMatchNumber.i
  Protected i.i, j.i, ErrorCode.l, EleCount.i, Pos.i
 
  ; Initialize
  MinDistance = 9999
  BestMatchNumber = 0
  ErrorCode = 0
  EleCount = 0
 
  ; Validate input
  If U01 = "" Or U02 = ""
    Set_Error("Invalid input: Both U01 and U02 must be non-empty.")
    ErrorCode = 1
    Goto ExitPoint
  EndIf
 
  ; Count elements to initialize array size
  EleCount = CountString(U01, ",") + CountString(U01, ";") + 1
 
  ; Initialize the arrays
  Dim Ele.s(EleCount)
  Dim Numbers.i(EleCount)
 
  ; Manually split the list based on comma or semicolon
  i = 0
  While Len(U01) > 0
    Pos = FindString(U01, ",", 1)
    If Pos = 0
      Pos = FindString(U01, ";", 1)
    EndIf
   
    If Pos > 0
      Temp = Left(U01, Pos - 1)
      U01 = Mid(U01, Pos + 1)
    Else
      Temp = U01
      U01 = ""
    EndIf
   
    Ele(i) = Trim(Temp)
    i+1
  Wend
 
  ; Loop through each element in the list
  For i = 0 To ArraySize(Ele()) - 1
    Element = Trim(Ele(i))
   
    ; Skip empty elements
    If Element = ""
      Continue
    EndIf
   
; Extract the numeric value if present
For j = 1 To Len(Element)
  If Asc(Mid(Element, j, 1)) >= 48 And Asc(Mid(Element, j, 1)) <= 57
    Number + Mid(Element, j, 1)
  Else
    Break
  EndIf
Next j
   
    ; Clean the element
    CleanElement = LTrim(Element, Number + ".- ")
   
    ; Assign a number if not present
    If Number = ""
      Number = Str(i + 1)
    EndIf
   
    ; Store the number
    Numbers(i) = Val(Number)
   
    ; Compare using LevenshteinDistance
    CurrentDistance = LevenshteinDistance(LCase(CleanElement), LCase(U02))
   
    ; Update the best match
    If CurrentDistance < MinDistance
      MinDistance = CurrentDistance
      BestMatchNumber = Numbers(i)
    EndIf
   
    ; Reset for the next iteration
    Number = ""
  Next i
 
  ; Single exit point
ExitPoint:
  If ErrorCode = 0
    ProcedureReturn BestMatchNumber
  Else
    ProcedureReturn -1
  EndIf
EndProcedure

#45
These days all Telescopes searching for Intelligent life are directed away from Earth :-).



#46
OxygenBasic / How about using the Whisper-AP...
Last post by Theo Gottwald - September 15, 2023, 10:28:46 AM
Why You Should Start Using Whisper for Speech-to-Text: A Game-Changer from OpenAI

Hey everyone! 🌟

Are you tired of wrestling with Windows' built-in speech recognition? Do you find yourself thinking, "I could've typed this faster!"? Well, I've got some fantastic news for you. 🎉

Introducing Whisper by OpenAI 🎙�

Whisper is not just another speech-to-text system; it's a revolution! Here's why you should consider making the switch:

  * 🚀 Speed: It's incredibly fast and efficient.
  * 🧠 Smart: It understands you, really understands you!
  * 💡 Integration with GPT-3.5: For truly intelligent instructions.

Local vs. Cloud: Choose Your Whisper 🏠☁️

  * Local Version: Free to install and use.
  * Cloud Version: Super affordable, with all the heavy lifting done on OpenAI's servers.

The Future is Here: Talk to Your Editor 🗨�🖋�

Imagine an editor that you can control not just by typing but by speaking to it. That's right, you can now talk your code into existence!

But Wait, There's More: GPT-4 Integration 🤖

You can even connect your editor to GPT-4 via API and have it write your code for you. While GPT-4 might not be an expert in every programming language, you can guide it with templates and examples.

For instance:

You could say, "Here's how my code starts... please complete it." With a few samples, GPT-4 can generate code in almost any language. It's like having an engineer who knows 100 programming languages at your fingertips!

The Bottom Line 🌟

Whisper is a game-changer. It's time to step into the future and unleash the full potential of speech-to-text and AI in your projects.

So, what are you waiting for?
Give Whisper a try and elevate your coding experience to the next level! 🚀

Here is a working Implementation for Purebasic.

You have an Editor-Project?
Adding Whisper and GPT-4 may be a game-changer.

Implementing WHISPER with Purebasic

I have no idea if it could have been done in O2 like that.
What do you think?
#47
Implementing the Whisper API for SPR: A Journey Through Speech-to-Text and Beyond

Hello fellow developers and tech enthusiasts! 🌟

Today, I want to share my experience implementing the Whisper API for SPR. But first, let's answer the question that might be on your mind:

What is Whisper? 🤔

Whisper is, arguably, the world's most advanced "Speech-to-Text" system. Here's why it's so cool:

  * 🗨� No Training Required: Just speak, and it writes down what you say.
  * 📝 GPT-3 Integration: You can even have GPT-3 correct the transcribed text.
  * 🌍 Multilingual Support: It understands nearly 100 languages and can translate them to English or transcribe as is.

Local vs. Online Versions 🏠☁️

  * Local Version: Requires installation and is resource-intensive.
  * Online Version: A cost-effective cloud service by OpenAI. This is the version we're using here.

Challenges and Solutions 🛠�

Implementing Whisper wasn't a walk in the park, especially with Powerbasic's limitations, such as:

  * Web Access and Proxy Servers
  * Lack of support for Multi-Part HTTP Requests

I initially found some code on the Purebasic Forum, but it wasn't plug-and-play. After diving deep into Multi-Part Requests, I managed to get it working.

Customization and Versatility 🎛�

I made several changes to adapt the library for my specific task: implementing OpenAI's Whisper API. Now that it's compatible with OpenAI, you can use this library for various other API-related tasks.

Note: I used some global variables, so it's not ready to run "out of the box."

How to Use Whisper with an .mp3 File 🎵

To call Whisper with an ".mp3 file," you would proceed as follows:


  ; Initialize a new multipart form data request
  m = MPFR_Create()
 
  ; Add the MP3 data to the request
  ; MPFR_AddDataFile(m,"file",*mp3Memory, mp3Size,"Zahlen_PCM16.wav", MimeType("audio/wav"))
  ; S03 - Filename mit Endung
   S04=MimeType(S03)
   MPFR_AddDataFile(m,"file",*mp3Memory, mp3Size,S03, S04)
   MPFR_AddTextField(m, "model", modelID)
 
  ; Send the request to the OpenAI API in headers
  status = MPFR_Send_with_API_Key(m, endP)
  serverResponse = MPFRequest(m)\response_message
 
  If status = #False   
    AI_Return=serverResponse
    Set_Error("Error: Failed to send HTTP request")
    Goto ExitPoint
  EndIf


Below is the Library for Purebasic.
That's it for now! If you have any questions or need further clarification, feel free to ask.

Happy coding! 🚀




; https://www.purebasic.fr/english/viewtopic.php?f=12&t=77006
;
; XIncludeFile "MultipartFormDataRequests.pbi"
;
; img = CreateImage(#PB_Any,400,400,32,#Blue)
;
; UseJPEGImageEncoder()
; *ImgBuffer = EncodeImage(img,#PB_ImagePlugin_JPEG)
; ImageLen.i = MemorySize(*ImgBuffer)
;
; m.i = MPFR_Create()
; MPFR_AddData(m,"filedata",*ImgBuffer,ImageLen,MimeTypeForFile("1.jpg"))
; MPFR_AddTextField(m,"onlinefn","my_online_file.jpg")
; If MPFR_Send(m,"https://www.mywebsite.com/MPF_File_Receiver.php")
;   wb.i = Val(StringField(MPFRequest(m)\response_message,2,c32))
;   If wb = ImageLen
;     Debug "success"
;   EndIf
; EndIf
; MPFR_Free(m)
;
; FreeMemory(*ImgBuffer)
;--------------------------------------------------------------------
;
;--------------------------------------------------------------------
Global c34.s{1} = Chr(34)
;--------------------------------------------------------------------
;
;--------------------------------------------------------------------
CompilerIf Defined(RandomCharacters,#PB_Procedure)=0
;--------------------------------------------------------------------
;
;-------------------------------------------------------------------- 
  Macro RandomLetter()
    Chr(65+Random(25))
  EndMacro
;--------------------------------------------------------------------
;
;-------------------------------------------------------------------- 
  Procedure.s RandomCharacters(l.i)   
    t.s   
    If l>0
      For a = 1 To l
        Select Random(2)
          Case 0
            t + Str(Random(9))
          Case 1
            t + RandomLetter()
          Case 2
            t + LCase(RandomLetter())
        EndSelect
      Next a
    EndIf   
    ProcedureReturn t   
  EndProcedure
;--------------------------------------------------------------------
;
;-------------------------------------------------------------------- 
 Procedure.s FormatURLParameter(t.s)
    t = ReplaceString(t,"?","%3F")
    t = ReplaceString(t,"/","%2F")
    t = URLEncoder(t)
    ProcedureReturn t
  EndProcedure
;--------------------------------------------------------------------
;
;-------------------------------------------------------------------- 
CompilerEndIf
;--------------------------------------------------------------------
;
;--------------------------------------------------------------------
Procedure.s MimeType(ext.s)
  ext = RemoveString(LCase(ext),".")
  Select ext
    Case "txt"
      ProcedureReturn "text/plain"
    Case "json"
      ProcedureReturn "application/json"
    Case "xml"
      ProcedureReturn "application/xml"
    Case "mp3", "ogg", "m4a","wav","oga","flac","mpga"
      ProcedureReturn "audio/"+ext
    Case "jpg", "jpeg"
      ProcedureReturn "image/jpeg"
    Case "png", "gif", "webp"
      ProcedureReturn "image/"+ext
    Case "mp4", "webm","mpeg"
      ProcedureReturn "video/"+ext
  EndSelect
EndProcedure
;--------------------------------------------------------------------
;
;--------------------------------------------------------------------

Enumeration 1
  #MPFR_FieldType_File
  #MPFR_FieldType_Data
  #MPFR_FieldType_Text
  #MPFR_FieldType_Data_File
EndEnumeration
;--------------------------------------------------------------------
;
;--------------------------------------------------------------------
Structure MPFR_Field_Structure
  field_type.b
 
  Map field_parameter.s()
 
  Post.s
  PostLen.i
  ContentLen.i
  filename.s
  field_name.s
  text.s
 
  fn.s
 
  *buffer
  DataLen.i
  mime.s
EndStructure
;--------------------------------------------------------------------
;
;--------------------------------------------------------------------
Structure MPFR_URLParameter_Structure
  name.s
  value.s
EndStructure
;--------------------------------------------------------------------
;
;--------------------------------------------------------------------
Structure MPFRequestStructure
  active.b
  List url_parameter.MPFR_URLParameter_Structure()
  List field.MPFR_Field_Structure()
 
  response_message.s
  status_code.i
  error_message.s
EndStructure
;--------------------------------------------------------------------
;
;--------------------------------------------------------------------
Global Dim MPFRequest.MPFRequestStructure(1)
;--------------------------------------------------------------------
;
;--------------------------------------------------------------------

Procedure.i MPFR_Create()
  reqs = ArraySize(MPFRequest())
  For q = 1 To reqs
    If Not MPFRequest(q)\active
      MPFRequest(q)\active = #True
      ProcedureReturn q
    EndIf
  Next q
 
  reqs+1 : ReDim MPFRequest(reqs)
  MPFRequest(reqs)\active = #True
  ProcedureReturn reqs
 
EndProcedure

;--------------------------------------------------------------------
;
;--------------------------------------------------------------------

Procedure.b MPFR_AddFile(q.i,field_name.s,fn.s)
  AddElement(MPFRequest(q)\field())
  With MPFRequest(q)\field()
    \field_type = #MPFR_FieldType_File
    \field_parameter("name") = field_name
    \fn = fn
    ;\mime = MimeTypeForFile(fn)
  EndWith
EndProcedure
;--------------------------------------------------------------------
;
;--------------------------------------------------------------------

Procedure.b MPFR_AddTextField(q.i,field_name.s,txt.s)
  AddElement(MPFRequest(q)\field())
  With MPFRequest(q)\field()
    \field_type = #MPFR_FieldType_Text
    \field_parameter("name") = field_name
    \text = txt
    ;R("TEXT: *"+txt+"*")
  EndWith
EndProcedure
;--------------------------------------------------------------------
;
;--------------------------------------------------------------------

Procedure.b MPFR_AddData(q.i,field_name.s,*SourceBuffer,datalen.i,mime.s)
  AddElement(MPFRequest(q)\field())
  With MPFRequest(q)\field()
    \field_type = #MPFR_FieldType_Data
    \field_parameter("name") = field_name
    \buffer = AllocateMemory(datalen+2)
    CopyMemory(*SourceBuffer,\buffer,datalen)
    \DataLen = datalen
    \field_name = field_name
    \mime = mime
  EndWith
EndProcedure
;--------------------------------------------------------------------
;
;--------------------------------------------------------------------
Procedure.b MPFR_AddDataFile(q.i, field_name.s, *SourceBuffer, dataLen.l, filename.s, mime.s)
  AddElement(MPFRequest(q)\field())
  With MPFRequest(q)\field()
    \field_type = #MPFR_FieldType_Data_File  ; New field type
    \field_parameter("name") = field_name   ; Name of the field
     \buffer = AllocateMemory(datalen+2)
    CopyMemory(*SourceBuffer,\buffer,datalen)                       ; Pointer to the binary data
    \DataLen = DataLen                      ; Length of the binary data
    \filename = filename                    ; Name of the file
    \field_name = field_name
    \mime = mime                            ; MIME type of the file
  EndWith
EndProcedure

;--------------------------------------------------------------------
;
;--------------------------------------------------------------------
Procedure.b MPFR_AddJSON(q.i,field_name.s,js.i)
  AddElement(MPFRequest(q)\field())
  With MPFRequest(q)\field()
    \field_type = #MPFR_FieldType_Data
    \mime = MimeType("json")
    \field_parameter("name") = field_name
    t.s = ComposeJSON(js)
    \DataLen = StringByteLength(t,#PB_UTF8)
    \buffer = AllocateMemory(\DataLen+2)
    PokeS(\buffer,t,-1,#PB_UTF8)
  EndWith
EndProcedure
;--------------------------------------------------------------------
;
;--------------------------------------------------------------------

Procedure.b MPFR_AddXML(q.i,field_name.s,xm.i)
  AddElement(MPFRequest(q)\field())
  With MPFRequest(q)\field()
    \field_type = #MPFR_FieldType_Data
    \mime = MimeType("xml")
    \field_parameter("name") = field_name
    \DataLen = ExportXMLSize(xm)
    \buffer = AllocateMemory(\DataLen+2)
    ExportXML(xm,\buffer,\DataLen)
  EndWith
EndProcedure
;--------------------------------------------------------------------
;
;--------------------------------------------------------------------

Procedure.b MPFR_AddFieldParameter(q.i,attrname.s,attrvalue.s)
  MPFRequest(q)\field()\field_parameter(attrname) = attrvalue
EndProcedure
;--------------------------------------------------------------------
;
;--------------------------------------------------------------------

Procedure.b MPFR_AddURLParameter(q.i,param_name.s,param_value.s)
  AddElement(MPFRequest(q)\url_parameter())
  With MPFRequest(q)\url_parameter()
    \name = param_name
    \value = param_value
  EndWith
EndProcedure
;--------------------------------------------------------------------
;
;--------------------------------------------------------------------

Procedure.b MPFR_Send(q.i,raw_u.s)
  With MPFRequest(q)   
    Repeat
      boundary.s = RandomCharacters(50)
      BoundaryLen.i = StringByteLength(boundary, #PB_UTF8)
      ;R(boundary+c13+"LEN: "+Str(BoundaryLen))
      If BoundaryLen>70 : Continue : EndIf
      violation.b = #False
      ForEach \field()
        If \field()\field_type=#MPFR_FieldType_Text And FindString(\field()\text,boundary,0,#PB_String_NoCase)
          violation = #True
          Break
        EndIf
      Next
    Until Not violation
   
   
    TotalBufferSize.i = 0
    ForEach \field()
      \field()\Post = #CRLF$ + "--" + boundary + #CRLF$
      ;\field()\Post + "Content-Disposition: form-data; name="+c34+\field()\field_name+c34 + #CRLF$
      ;\field()\Post + "Content-Disposition: form-data; name="+c34+\field()\field_name+c34+"; filename="+c34+"give_filename.jpg"+c34+"; " + #CRLF$
      cdfldarr.s = ""
      ForEach \field()\field_parameter()
        cdfldarr + MapKey(\field()\field_parameter())+"="+c34+\field()\field_parameter()+c34+"; "
      Next
      \field()\Post + "Content-Disposition: form-data; " + cdfldarr + #CRLF$
 
      Select \field()\field_type
         
        Case #MPFR_FieldType_File
          \field()\Post + "Content-Type: "+MimeType(GetExtensionPart(\field()\fn)) + #CRLF$
          \field()\ContentLen = FileSize(\field()\fn)         
         
        Case #MPFR_FieldType_Data
          \field()\Post + "Content-Type: "+\field()\mime + #CRLF$
          \field()\ContentLen = \field()\DataLen
         
         
        Case #MPFR_FieldType_Text
          \field()\Post + "Content-Type: "+MimeType("txt") + #CRLF$
          \field()\ContentLen = StringByteLength(\field()\text,#PB_UTF8)
         
         Case #MPFR_FieldType_Data_File
        \field()\Post + "Content-Disposition: form-data; name="+c34+\field()\field_name+c34+"; filename="+c34+"give_filename.jpg"+c34+"; " + #CRLF$
        \field()\Post + "Content-Type: image/jpeg" + #CRLF$  ; You can modify this MIME type based on the actual file type.
        \field()\ContentLen = \field()\DataLen  ; Assuming DataLen contains the length of the binary data 
         
        Default
          MessageRequester("Error","Don't know what to do with field type "+Str(\field()\field_type))
         
         
      EndSelect
     
      \field()\Post + #CRLF$
      \field()\PostLen = StringByteLength(\field()\Post, #PB_UTF8)
      TotalBufferSize + \field()\PostLen + \field()\ContentLen
    Next
   
   
    TotalBufferSize + 2+2+BoundaryLen+2+2
    ;R("TOTAL SIZE FOR BUFFER: "+StrD( TotalBufferSize /1000/1000) )
   
    *Buffer = AllocateMemory(TotalBufferSize, #PB_Memory_NoClear)
    If Not *Buffer
      Debug "failure to allocate memory"
      ProcedureReturn #False
    EndIf
    *BufferPosition = *Buffer
   
   
    ForEach \field()
      PokeS(*BufferPosition, \field()\Post, -1, #PB_UTF8|#PB_String_NoZero)
      *BufferPosition + \field()\PostLen
     
      Select \field()\field_type
        Case #MPFR_FieldType_File
          fs = FileSize(\field()\fn)
          f = ReadFile(#PB_Any,\field()\fn,#PB_File_SharedRead)
          ;R(\field()\fn+c13+"SIZE: "+Str(fs)+c13+"F: "+Str(f))
          ReadData(f,*BufferPosition,\field()\ContentLen)
          CloseFile(f)
        Case #MPFR_FieldType_Data
          CopyMemory(\field()\buffer, *BufferPosition, \field()\ContentLen)
        Case #MPFR_FieldType_Text
          PokeS(*BufferPosition, \field()\text, -1, #PB_UTF8|#PB_String_NoZero)
        Case #MPFR_FieldType_Data_File 
          CopyMemory(\field()\buffer, *BufferPosition, \field()\ContentLen)
      EndSelect
      *BufferPosition + \field()\ContentLen
    Next
   
   
    PokeS(*BufferPosition, #CRLF$ + "--" + boundary + "--" + #CRLF$, -1, #PB_UTF8|#PB_String_NoZero)
    *BufferPosition + (2+2+BoundaryLen+2+2)
   
   
   
    u.s = raw_u
    If ListSize(\url_parameter())
      u + "?"
      FirstElement(\url_parameter())
      u + \url_parameter()\name+"=" + FormatURLParameter(\url_parameter()\value)
      While NextElement(\url_parameter())
        u + "&"+\url_parameter()\name+"=" + FormatURLParameter(\url_parameter()\value)
      Wend
    EndIf
   
   
    NewMap Header.s()
    Header("Content-Type") = "multipart/form-data; boundary=" + boundary
    Header("Content-Length") = Str(TotalBufferSize)
   
    HttpRequest.i = HTTPRequestMemory(#PB_HTTP_Post, u, *Buffer, TotalBufferSize, 0, Header())
   
    If HttpRequest
      \response_message = HTTPInfo(HTTPRequest, #PB_HTTP_Response)
      \status_code = Val(HTTPInfo(HTTPRequest,#PB_HTTP_StatusCode))
      \error_message = HTTPInfo(HTTPRequest,#PB_HTTP_ErrorMessage)
      ;MBX("Error:"+\error_message)
      ;MBX("Response:"+\response_message)
      If \status_code=200
        ;MBX( "RT: *"+\response_message+"*")
        status.b = #True
      Else
        Set_Error("Response: *"+\response_message+"*")
        Set_Error("ERROR: "+\error_message+"*")
      EndIf
      FinishHTTP(HttpRequest)
    EndIf
    FreeMemory(*Buffer)   
    ProcedureReturn status   
  EndWith
EndProcedure
;--------------------------------------------------------------------
;
;--------------------------------------------------------------------
; U01 -\field()\fn
; U01 - Dateiname
Procedure.s MPFR_GetContent_Type(U01.s="")
  Protected.s S02,S03   
  S02=Trim(U01) 
  If Len(U01)=0
    S02=MPFRequest(q)\field()\fn
  EndIf 
  If FindString(S02,"\")>0
    S02=GetFilePart(S02)
  EndIf 
  S03="Content-Type: "+MimeType(GetExtensionPart(S02))
  ProcedureReturn S03
EndProcedure 
;--------------------------------------------------------------------
;
;--------------------------------------------------------------------
; Use the Open AI-API-Key
Procedure.b MPFR_Send_with_API_Key(q.i, raw_u.s)
  With MPFRequest(q)   
    Repeat
      boundary.s = RandomCharacters(50)
      BoundaryLen.i = StringByteLength(boundary, #PB_UTF8)
      ;R(boundary+c13+"LEN: "+Str(BoundaryLen))
      If BoundaryLen>70 : Continue : EndIf
      violation.b = #False
      ForEach \field()
        If \field()\field_type=#MPFR_FieldType_Text And FindString(\field()\text,boundary,0,#PB_String_NoCase)
          violation = #True
          Break
        EndIf
      Next
    Until Not violation
   
   
    TotalBufferSize.i = 0
    ForEach \field()
      \field()\Post = #CRLF$ + "--" + boundary + #CRLF$
      ;\field()\Post + "Content-Disposition: form-data; name="+c34+\field()\field_name+c34 + #CRLF$
      ;\field()\Post + "Content-Disposition: form-data; name="+c34+\field()\field_name+c34+"; filename="+c34+"give_filename.jpg"+c34+"; " + #CRLF$
      ; Kommentar entfernt     
      cdfldarr.s = ""
     
      ForEach \field()\field_parameter()
        cdfldarr + MapKey(\field()\field_parameter())+"="+c34+\field()\field_parameter()+c34+"; "
      Next
      \field()\Post + "Content-Disposition: form-data; " + cdfldarr + #CRLF$
 
      Select \field()\field_type
        Case #MPFR_FieldType_File
          \field()\Post + MPFR_GetContent_Type() + #CRLF$
          \field()\ContentLen = FileSize(\field()\fn)
         
         
        Case #MPFR_FieldType_Data
          \field()\Post + "Content-Type: "+\field()\mime + #CRLF$         
          \field()\ContentLen = \field()\DataLen
         
         
        Case #MPFR_FieldType_Text
          \field()\Post + "Content-Type: "+MimeType("txt") + #CRLF$
          \field()\ContentLen = StringByteLength(\field()\text,#PB_UTF8)
         
        Case #MPFR_FieldType_Data_File
          \field()\Post = #CRLF$ + "--" + boundary + #CRLF$
          \field()\Post + "Content-Disposition: form-data; " + cdfldarr           
          S02.s= \field()\Post
          S02 + "filename="+c34+\field()\filename+c34+"; " + #CRLF$
           \field()\Post=S02           
           S02=MPFR_GetContent_Type(\field()\filename)+#CRLF$  ; You can modify this MIME type based on the actual file type.
           \field()\Post + S02
           \field()\ContentLen = \field()\DataLen  ; Assuming DataLen contains the length of the binary data           
         ;MBX(\field()\Post)
        Default
          MessageRequester("Error","Don't know what to do with field type "+Str(\field()\field_type))
                   
      EndSelect
      \field()\Post + #CRLF$
      \field()\PostLen = StringByteLength(\field()\Post, #PB_UTF8)
      TotalBufferSize + \field()\PostLen + \field()\ContentLen
    Next
   
   
    TotalBufferSize + 2+2+BoundaryLen+2+2
    ;R("TOTAL SIZE FOR BUFFER: "+StrD( TotalBufferSize /1000/1000) )
   
    *Buffer = AllocateMemory(TotalBufferSize, #PB_Memory_NoClear)
    If Not *Buffer
      Debug "failure to allocate memory"
      ProcedureReturn #False
    EndIf
    *BufferPosition = *Buffer
   
   
    ForEach \field()
      PokeS(*BufferPosition, \field()\Post, -1, #PB_UTF8|#PB_String_NoZero)
      *BufferPosition + \field()\PostLen
     
      Select \field()\field_type
        Case #MPFR_FieldType_File
          fs = FileSize(\field()\fn)
          f = ReadFile(#PB_Any,\field()\fn,#PB_File_SharedRead)
          ;R(\field()\fn+c13+"SIZE: "+Str(fs)+c13+"F: "+Str(f))
          ReadData(f,*BufferPosition,\field()\ContentLen)
          CloseFile(f)
        Case #MPFR_FieldType_Data
          CopyMemory(\field()\buffer, *BufferPosition, \field()\ContentLen)
        Case #MPFR_FieldType_Text
          PokeS(*BufferPosition, \field()\text, -1, #PB_UTF8|#PB_String_NoZero)
         Case #MPFR_FieldType_Data_File 
          CopyMemory(\field()\buffer, *BufferPosition, \field()\ContentLen) 
      EndSelect
      *BufferPosition + \field()\ContentLen
    Next
   
   
    PokeS(*BufferPosition, #CRLF$ + "--" + boundary + "--" + #CRLF$, -1, #PB_UTF8|#PB_String_NoZero)
    *BufferPosition + (2+2+BoundaryLen+2+2)
   
    u.s = raw_u
    If ListSize(\url_parameter())
      u + "?"
      FirstElement(\url_parameter())
      u + \url_parameter()\name+"=" + FormatURLParameter(\url_parameter()\value)
      While NextElement(\url_parameter())
        u + "&"+\url_parameter()\name+"=" + FormatURLParameter(\url_parameter()\value)
      Wend
    EndIf
   
 ; Before sending the HTTP request, add the API Key to the headers.
    NewMap Header.s()
    Header("Content-Type") = "multipart/form-data; boundary=" + boundary
    Header("Content-Length") = Str(TotalBufferSize)
    Header("Authorization") = "Bearer " + AI_OKEY ; <- Include API Key here
   
    HttpRequest.i = HTTPRequestMemory(#PB_HTTP_Post, u, *Buffer, TotalBufferSize, 0, Header())
    ;FreeMemory(*Buffer)
    If HttpRequest
      \response_message = HTTPInfo(HTTPRequest, #PB_HTTP_Response)
      \status_code = Val(HTTPInfo(HTTPRequest,#PB_HTTP_StatusCode))
      \error_message = HTTPInfo(HTTPRequest,#PB_HTTP_ErrorMessage)
      ;MBX("Error:"+\error_message)
     
      ;SetClipboardText("Error:"+\error_message)
      ;MBX("Response:"+\response_message)
     
      If \status_code=200
        ;MBX( "RT: *"+\response_message+"*")
        status.b = #True
      Else
        Set_Error("Response: *"+\response_message+"*")
        Set_Error("ERROR: "+\error_message+"*")
      EndIf
      FinishHTTP(HttpRequest)
    EndIf
    FreeMemory(*Buffer)   
    ProcedureReturn status   
  EndWith
EndProcedure
;--------------------------------------------------------------------
;
;--------------------------------------------------------------------
Procedure.b MPFR_Free(q.i)
  With MPFRequest(q)
    ForEach \field()
      If \field()\buffer<>0
        FreeMemory(\field()\buffer)
      EndIf
    Next
    ClearList(\field())
    \active = #False
  EndWith
EndProcedure
;--------------------------------------------------------------------
;
;--------------------------------------------------------------------

#48
30 years younger? He looks like he's in his fifties, not 24. Another guy trying to sell a book.

#49
I AVOID 5 FOODS & my body is 30 YEARS YOUNGER! Harvard Genetics Professor David Sinclair

Healthy Long Life
8 sept 2023


#50
General Discussion / Sockets, Sparks, and Magic Smo...
Last post by Charles Pegge - September 13, 2023, 01:09:48 PM
Best presentation yet.

Sockets, Sparks, and Magic Smoke - Dylan Beattie - NDC London 2023
NDC Conferences
9 may 2023