Jump to content

Skype API


Recommended Posts

I am using this code to check that Skype.exe is running:

$App = "Skype.exe"

$PID = ProcessExists($App)

If $PID = 0 And $App <> "" Then

Run("Skype.exe")

Exit

EndIf

Now that works fine but it does not tell me if Skype is actually OnLine and can take calls.

Skype users would be familure with the process that allows you to change the OnLine status for Skype whilst it is running from OnLIne to Not Available, Invisible as well as others].

Can anyone help me with a code fragment that allows an AutoIT script to read the onLine status code that is active when Skype is running.

Help is always appreciated

Link to comment
Share on other sites

I am pretty sure the API functions will come in the form of a DLL. The functions will be loaded through there. And out of thought, how the hell do you think that your script will notify you without even hooking the program or giving direction for it to?

Thank you for the informative response. In my ProcessExists example I was simply demonstrating that I had an elementary understanding of the function. Perhaps the Forum would prefer that I had posted this example.

If ProcessExists("notepad.exe") Then

MsgBox(0, "Example", "Notepad is running.")

EndIf

Link to comment
Share on other sites

Create an object Skype and follow the commands posted here https://developer.skype.com/Docs/Skype4COMLib

You can go through the forum if you have questions regarding the Skype api.

Thanks for the pointer and this code opens Skype if it is not running

; Create a Skype4COM object:

$oSkype = ObjCreate("Skype4COM.Skype")

If Not $oSkype.Client.IsRunning Then

$oSkype.Client.Start()

EndIf

I would really appreciate if someone could show me how to convert this VB code into AutoIT Script

'// The AttachmentStatus event handler monitors attachment status and automatically attempts to reattach to the API following loss of connection:

Public Sub Skype_AttachmentStatus(ByVal aStatus)

WScript.Echo ">Attachment status " & oSkype.Convert.AttachmentStatusToText(aStatus)

If aStatus = oSkype.Convert.TextToAttachmentStatus("AVAILABLE") Then oSkype.Attach() End If

End Sub

Link to comment
Share on other sites

I've converted the Attach.vbs script on the Skype4COMLib site to AutoIt:

;// Create a Skype4COM object:
$oSkype = ObjCreate("Skype4COM.Skype")

;// Start the Skype client:
If Not $oSkype.Client.IsRunning Then
    $oSkype.Client.Start()
EndIf

;// Connect to the Skype API with protocol version 5 (the default version):
$oSkype.Attach(5)

;// When attached to the API, send repeated commands to the API to test if they succeed:
While 1 
  Sleep(1000)
  If $oSkype.AttachmentStatus = $oSkype.Convert.TextToAttachmentStatus("SUCCESS") Then 
    MsgBox(0,"","PING..")
    $oSkype.SendCommand($oSkype.Command(0, "PING","PONG",TRUE))
  ;oSkype.SendCommand(oSkype.Command(0, "PING")) 
    MsgBox(0,"","ok")
  EndIf
WEnd
 
;// The AttachmentStatus event handler monitors attachment status and returns the Skypename of the user when the status is "success":
Func Skype_AttachmentStatus($aStatus)
    MsgBox(0,"Attachment status",$oSkype.Convert.AttachmentStatusToText($aStatus))
    If $aStatus = $oSkype.Convert.TextToAttachmentStatus("AVAILABLE") Then
        $oSkype.Attach()
    EndIf
    If $aStatus = $oSkype.Convert.TextToAttachmentStatus("SUCCESS") Then
        MsgBox(0,"","Current user is " & $oSkype.CurrentUserHandle)
    EndIf  
EndFunc
Certifications: A+, Network+, Security+, Linux+, LPIC-1, MCSA | Languages: AutoIt, C, SQL, .NETBooks: AutoIt v3: Your Quick Guide - $7.99 - O'Reilly Media - September 2007-------->[u]AutoIt v3 Development - newbie to g33k[/u] - Coming Soon - Fate Publishing - Spring 2013UDF Libraries: SkypeCOM UDF Library | ADUC Computers OU Cleanup | Find PixelChecksumExamples: Skype COM Examples - Skype4COMLib Examples converted from VBS to AutoIt
Link to comment
Share on other sites

I've converted the Attach.vbs script on the Skype4COMLib site to AutoIt:

;// Create a Skype4COM object:
$oSkype = ObjCreate("Skype4COM.Skype")

;// Start the Skype client:
If Not $oSkype.Client.IsRunning Then
    $oSkype.Client.Start()
EndIf

;// Connect to the Skype API with protocol version 5 (the default version):
$oSkype.Attach(5)

;// When attached to the API, send repeated commands to the API to test if they succeed:
While 1 
  Sleep(1000)
  If $oSkype.AttachmentStatus = $oSkype.Convert.TextToAttachmentStatus("SUCCESS") Then 
    MsgBox(0,"","PING..")
    $oSkype.SendCommand($oSkype.Command(0, "PING","PONG",TRUE))
 ;oSkype.SendCommand(oSkype.Command(0, "PING")) 
    MsgBox(0,"","ok")
  EndIf
WEnd
 
;// The AttachmentStatus event handler monitors attachment status and returns the Skypename of the user when the status is "success":
Func Skype_AttachmentStatus($aStatus)
    MsgBox(0,"Attachment status",$oSkype.Convert.AttachmentStatusToText($aStatus))
    If $aStatus = $oSkype.Convert.TextToAttachmentStatus("AVAILABLE") Then
        $oSkype.Attach()
    EndIf
    If $aStatus = $oSkype.Convert.TextToAttachmentStatus("SUCCESS") Then
        MsgBox(0,"","Current user is " & $oSkype.CurrentUserHandle)
    EndIf  
EndFunc
Thats really cool but with Skype "OnLIne' I am not getting $aStatus Message
Link to comment
Share on other sites

Thats really cool but with Skype "OnLIne' I am not getting $aStatus Message

Oops! Sorry, long day... :)

Try this:

;// Create a Skype4COM object:
$oSkype = ObjCreate("Skype4COM.Skype")

;// Start the Skype client:
If Not $oSkype.Client.IsRunning Then
    $oSkype.Client.Start()
EndIf

;// Connect to the Skype API with protocol version 5 (the default version):
$oSkype.Attach(5)

;// When attached to the API, send repeated commands to the API to test if they succeed:
While 1 
  Sleep(1000)
  If $oSkype.AttachmentStatus = $oSkype.Convert.TextToAttachmentStatus("SUCCESS") Then 
    MsgBox(0,"","PING..")
    $oSkype.SendCommand($oSkype.Command(0, "PING","PONG",TRUE))
    Skype_AttachmentStatus()
  EndIf
WEnd
 
;// The AttachmentStatus event handler monitors attachment status and returns the Skypename of the user when the status is "success":
Func Skype_AttachmentStatus()
    $aStatus = $oSkype.AttachmentStatus
    MsgBox(0,"Attachment status",$oSkype.Convert.AttachmentStatusToText($aStatus))
    If $aStatus = $oSkype.Convert.TextToAttachmentStatus("AVAILABLE") Then
        $oSkype.Attach()
    EndIf
    If $aStatus = $oSkype.Convert.TextToAttachmentStatus("SUCCESS") Then
        MsgBox(0,"","Current user is " & $oSkype.CurrentUserHandle)
    EndIf  
EndFunc
Certifications: A+, Network+, Security+, Linux+, LPIC-1, MCSA | Languages: AutoIt, C, SQL, .NETBooks: AutoIt v3: Your Quick Guide - $7.99 - O'Reilly Media - September 2007-------->[u]AutoIt v3 Development - newbie to g33k[/u] - Coming Soon - Fate Publishing - Spring 2013UDF Libraries: SkypeCOM UDF Library | ADUC Computers OU Cleanup | Find PixelChecksumExamples: Skype COM Examples - Skype4COMLib Examples converted from VBS to AutoIt
Link to comment
Share on other sites

Oops! Sorry, long day... :)

Try this:

;// Create a Skype4COM object:
$oSkype = ObjCreate("Skype4COM.Skype")

;// Start the Skype client:
If Not $oSkype.Client.IsRunning Then
    $oSkype.Client.Start()
EndIf

;// Connect to the Skype API with protocol version 5 (the default version):
$oSkype.Attach(5)

;// When attached to the API, send repeated commands to the API to test if they succeed:
While 1 
  Sleep(1000)
  If $oSkype.AttachmentStatus = $oSkype.Convert.TextToAttachmentStatus("SUCCESS") Then 
    MsgBox(0,"","PING..")
    $oSkype.SendCommand($oSkype.Command(0, "PING","PONG",TRUE))
    Skype_AttachmentStatus()
  EndIf
WEnd
 
;// The AttachmentStatus event handler monitors attachment status and returns the Skypename of the user when the status is "success":
Func Skype_AttachmentStatus()
    $aStatus = $oSkype.AttachmentStatus
    MsgBox(0,"Attachment status",$oSkype.Convert.AttachmentStatusToText($aStatus))
    If $aStatus = $oSkype.Convert.TextToAttachmentStatus("AVAILABLE") Then
        $oSkype.Attach()
    EndIf
    If $aStatus = $oSkype.Convert.TextToAttachmentStatus("SUCCESS") Then
        MsgBox(0,"","Current user is " & $oSkype.CurrentUserHandle)
    EndIf  
EndFunc
Thanks for the update:

If you run the script when Skype is running it appears to work perfectly however if you close Skype and then run your script you get the following error:

>Running:(3.2.12.0):C:\Program Files\AutoIt3\autoit3.exe "C:\PhoneServer\Source Code\Skype.au3"

C:\PhoneServer\Source Code\Skype.au3 (10) : ==> The requested action with this object has failed.:

$oSkype.Attach(5)

$oSkype.Attach(5)^ ERROR

->13:46:19 AutoIT3.exe ended.rc:1

>Exit code: 1 Time: 31.333

Perhaps the issue is that Skype is still running its setup when the script runs the attach process???

Link to comment
Share on other sites

Thanks for the update:

If you run the script when Skype is running it appears to work perfectly however if you close Skype and then run your script you get the following error:

>Running:(3.2.12.0):C:\Program Files\AutoIt3\autoit3.exe "C:\PhoneServer\Source Code\Skype.au3"

C:\PhoneServer\Source Code\Skype.au3 (10) : ==> The requested action with this object has failed.:

$oSkype.Attach(5)

$oSkype.Attach(5)^ ERROR

->13:46:19 AutoIT3.exe ended.rc:1

>Exit code: 1 Time: 31.333

Perhaps the issue is that Skype is still running its setup when the script runs the attach process???

Whoops! I think I may have goofed that one up too... Try to replace $oSkype.Attach(5) with just $oSkype.Attach. The (5) is causing the problem.
Certifications: A+, Network+, Security+, Linux+, LPIC-1, MCSA | Languages: AutoIt, C, SQL, .NETBooks: AutoIt v3: Your Quick Guide - $7.99 - O'Reilly Media - September 2007-------->[u]AutoIt v3 Development - newbie to g33k[/u] - Coming Soon - Fate Publishing - Spring 2013UDF Libraries: SkypeCOM UDF Library | ADUC Computers OU Cleanup | Find PixelChecksumExamples: Skype COM Examples - Skype4COMLib Examples converted from VBS to AutoIt
Link to comment
Share on other sites

Whoops! I think I may have goofed that one up too... Try to replace $oSkype.Attach(5) with just $oSkype.Attach. The (5) is causing the problem.

That does not seem to help I tried both $oSkype.Attach and $oSkype.Attach() and got the same result [following example is for $oSkype.Attach()]

C:\PhoneServer\Source Code\Skype.au3 (10) : ==> The requested action with this object has failed.:

$oSkype.Attach()

$oSkype.Attach()^ ERROR

->13:59:19 AutoIT3.exe ended.rc:1

>Exit code: 1 Time: 31.337

Link to comment
Share on other sites

That does not seem to help I tried both $oSkype.Attach and $oSkype.Attach() and got the same result [following example is for $oSkype.Attach()]

C:\PhoneServer\Source Code\Skype.au3 (10) : ==> The requested action with this object has failed.:

$oSkype.Attach()

$oSkype.Attach()^ ERROR

->13:59:19 AutoIT3.exe ended.rc:1

>Exit code: 1 Time: 31.337

Wow, I must've been a bit too tired to poke around on this last night. Anyway, the object was failing because the script wasn't waiting for Skype to open before trying to attach. I put in a timeout loop that will force the script to wait until Skype is open. Give this a shot; if it doesn't work, just increase the Sleep() timeout.

;// Create a Skype4COM object:
$oSkype = ObjCreate("Skype4COM.Skype")

;// Start the Skype client:
If Not $oSkype.Client.IsRunning Then
    $oSkype.Client.Start()
    While 1
        If Not $oSkype.Client.IsRunning Then
            Sleep(2000)
        Else
            ExitLoop
        EndIf
    WEnd
EndIf

;// Connect to the Skype API with protocol version 5 (the default version):
$oSkype.Attach(5)

;// When attached to the API, send repeated commands to the API to test if they succeed:
While 1 
  Sleep(1000)
  If $oSkype.AttachmentStatus = $oSkype.Convert.TextToAttachmentStatus("SUCCESS") Then 
    MsgBox(0,"","PING..")
    $oSkype.SendCommand($oSkype.Command(0, "PING","PONG",TRUE))
    Skype_AttachmentStatus()
  EndIf
WEnd
 
;// The AttachmentStatus event handler monitors attachment status and returns the Skypename of the user when the status is "success":
Func Skype_AttachmentStatus()
    $aStatus = $oSkype.AttachmentStatus
    MsgBox(0,"Attachment status",$oSkype.Convert.AttachmentStatusToText($aStatus))
    If $aStatus = $oSkype.Convert.TextToAttachmentStatus("AVAILABLE") Then
        $oSkype.Attach()
    EndIf
    If $aStatus = $oSkype.Convert.TextToAttachmentStatus("SUCCESS") Then
        MsgBox(0,"","Current user is " & $oSkype.CurrentUserHandle)
    EndIf  
EndFunc
Edited by Airwolf123
Certifications: A+, Network+, Security+, Linux+, LPIC-1, MCSA | Languages: AutoIt, C, SQL, .NETBooks: AutoIt v3: Your Quick Guide - $7.99 - O'Reilly Media - September 2007-------->[u]AutoIt v3 Development - newbie to g33k[/u] - Coming Soon - Fate Publishing - Spring 2013UDF Libraries: SkypeCOM UDF Library | ADUC Computers OU Cleanup | Find PixelChecksumExamples: Skype COM Examples - Skype4COMLib Examples converted from VBS to AutoIt
Link to comment
Share on other sites

Wow, I must've been a bit too tired to poke around on this last night. Anyway, the object was failing because the script wasn't waiting for Skype to open before trying to attach. I put in a timeout loop that will force the script to wait until Skype is open. Give this a shot; if it doesn't work, just increase the Sleep() timeout.

;// Create a Skype4COM object:
$oSkype = ObjCreate("Skype4COM.Skype")

;// Start the Skype client:
If Not $oSkype.Client.IsRunning Then
    $oSkype.Client.Start()
    While 1
        If Not $oSkype.Client.IsRunning Then
            Sleep(2000)
        Else
            ExitLoop
        EndIf
    WEnd
EndIf

;// Connect to the Skype API with protocol version 5 (the default version):
$oSkype.Attach(5)

;// When attached to the API, send repeated commands to the API to test if they succeed:
While 1 
  Sleep(1000)
  If $oSkype.AttachmentStatus = $oSkype.Convert.TextToAttachmentStatus("SUCCESS") Then 
    MsgBox(0,"","PING..")
    $oSkype.SendCommand($oSkype.Command(0, "PING","PONG",TRUE))
    Skype_AttachmentStatus()
  EndIf
WEnd
 
;// The AttachmentStatus event handler monitors attachment status and returns the Skypename of the user when the status is "success":
Func Skype_AttachmentStatus()
    $aStatus = $oSkype.AttachmentStatus
    MsgBox(0,"Attachment status",$oSkype.Convert.AttachmentStatusToText($aStatus))
    If $aStatus = $oSkype.Convert.TextToAttachmentStatus("AVAILABLE") Then
        $oSkype.Attach()
    EndIf
    If $aStatus = $oSkype.Convert.TextToAttachmentStatus("SUCCESS") Then
        MsgBox(0,"","Current user is " & $oSkype.CurrentUserHandle)
    EndIf  
EndFunc
Hi thanks for your help. It works fine provided that you change $oSkype.Attach(5) to $oSkype.Attach.

Final question for you do you [todate I have had no response from the Skype Forum or found any information in their Knowledge Base and my difficulty understanding their documentation on Skype4COM) do you just happen to know what the $oSkype syntax is for Notifications - Status Notifications - Connection Status for the item called "connstatus'. Connstatus should return the Skype connection status be it OnLine, Away, Not Available, Silent, OffLine etc.

Link to comment
Share on other sites

Do you just happen to know what the $oSkype syntax is for Notifications - Status Notifications - Connection Status for the item called "connstatus'. Connstatus should return the Skype connection status be it OnLine, Away, Not Available, Silent, OffLine etc.

I've been converting all Skype COM VBS Example to AutoIt and I'll post them to the Example forum tomorrow. I'll post a link in this thread once I've posted the examples. I haven't seen anything dealing with Connstatus yet, but to find the statuses you've listed (Online, Away, Offline, etc.), you should use UserStatus.

Here is a loop you'll see in my converted examples that uses UserStatus:

$oSkype = ObjCreate("Skype4COM.Skype")

;// Verify that a user is signed in and online before continuing
While 1
    If $oSkype.CurrentUserStatus = $oSkype.Convert.TextToUserStatus("ONLINE") Then
        ExitLoop
    Else
        $oSkype.ChangeUserStatus($oSkype.Convert.TextToUserStatus("ONLINE"))
    EndIf
    Sleep(1000)
WEnd

I'd suggest waiting for my AutoIt conversions of the Skype COM VBS Examples, as you'll need the custom event handlers for Skype and AutoIt (for COM errors).

Certifications: A+, Network+, Security+, Linux+, LPIC-1, MCSA | Languages: AutoIt, C, SQL, .NETBooks: AutoIt v3: Your Quick Guide - $7.99 - O'Reilly Media - September 2007-------->[u]AutoIt v3 Development - newbie to g33k[/u] - Coming Soon - Fate Publishing - Spring 2013UDF Libraries: SkypeCOM UDF Library | ADUC Computers OU Cleanup | Find PixelChecksumExamples: Skype COM Examples - Skype4COMLib Examples converted from VBS to AutoIt
Link to comment
Share on other sites

Hi thanks for your help. It works fine provided that you change $oSkype.Attach(5) to $oSkype.Attach.

Final question for you do you [todate I have had no response from the Skype Forum or found any information in their Knowledge Base and my difficulty understanding their documentation on Skype4COM) do you just happen to know what the $oSkype syntax is for Notifications - Status Notifications - Connection Status for the item called "connstatus'. Connstatus should return the Skype connection status be it OnLine, Away, Not Available, Silent, OffLine etc.

I have been able to answer my own question and this gives you the numeric code 1 = OnLine 2. 3. .4. 5 = OffLine

If $oSkype.CurrentUserStatus = 1 Then ;[1 = OnLine 5 = OffLine]

Msgbox(0,"","OnLine")

Else

Msgbox(0,"","OffLine")

EndIf

Link to comment
Share on other sites

I have been able to answer my own question and this gives you the numeric code 1 = OnLine 2. 3. .4. 5 = OffLine

If $oSkype.CurrentUserStatus = 1 Then ;[1 = OnLine 5 = OffLine]

Msgbox(0,"","OnLine")

Else

Msgbox(0,"","OffLine")

EndIf

Looks like we came to the same conclusion. :)

FYI - If you add that to the script and Skype is not already open when it is run, the object will error out unless you have a custom error handler for COM objects. What happens is Skype launches, but the script continues before the user is logged in; the $oSkype object won't have a valid CurrentUserStatus property at the point when your If statement kicks in.

Certifications: A+, Network+, Security+, Linux+, LPIC-1, MCSA | Languages: AutoIt, C, SQL, .NETBooks: AutoIt v3: Your Quick Guide - $7.99 - O'Reilly Media - September 2007-------->[u]AutoIt v3 Development - newbie to g33k[/u] - Coming Soon - Fate Publishing - Spring 2013UDF Libraries: SkypeCOM UDF Library | ADUC Computers OU Cleanup | Find PixelChecksumExamples: Skype COM Examples - Skype4COMLib Examples converted from VBS to AutoIt
Link to comment
Share on other sites

I did not get to read your reply before I claimed to have found the solution. Anyway who found what and when does not matter other than I am now another step down the road of discovery. I look forward with considerable interest your next instalment.

Link to comment
Share on other sites

I did not get to read your reply before I claimed to have found the solution. Anyway who found what and when does not matter other than I am now another step down the road of discovery. I look forward with considerable interest your next instalment.

I was more alluding that great minds think alike :) ; I wasn't claiming that you didn't figure the solution out on your own... which you did since we posted at the same time.

I've got over half of the Skype VBS Examples converted to AutoIt. I'll definitely have the rest done tomorrow.

Certifications: A+, Network+, Security+, Linux+, LPIC-1, MCSA | Languages: AutoIt, C, SQL, .NETBooks: AutoIt v3: Your Quick Guide - $7.99 - O'Reilly Media - September 2007-------->[u]AutoIt v3 Development - newbie to g33k[/u] - Coming Soon - Fate Publishing - Spring 2013UDF Libraries: SkypeCOM UDF Library | ADUC Computers OU Cleanup | Find PixelChecksumExamples: Skype COM Examples - Skype4COMLib Examples converted from VBS to AutoIt
Link to comment
Share on other sites

I was more alluding that great minds think alike :) ; I wasn't claiming that you didn't figure the solution out on your own... which you did since we posted at the same time.

I've got over half of the Skype VBS Examples converted to AutoIt. I'll definitely have the rest done tomorrow.

In my part of the world it is claimed that great minds think alike [thats you and me] unfortunately some would prefer you to believe that small minds never differ.
Link to comment
Share on other sites

That does not seem to help I tried both $oSkype.Attach and $oSkype.Attach() and got the same result [following example is for $oSkype.Attach()]

C:\PhoneServer\Source Code\Skype.au3 (10) : ==> The requested action with this object has failed.:

$oSkype.Attach()

$oSkype.Attach()^ ERROR

->13:59:19 AutoIT3.exe ended.rc:1

>Exit code: 1 Time: 31.337

I've solved this problem by adding object error handler:
Global $ObjError = 0  ; to be checked to know if com error occurs. Must be reset after handling.

$ObjErrorObj = ObjEvent("AutoIt.Error","ObjErrorHandler") ; Install a custom error handler (thanks to Jos, for pointing this out)

;// Create a Skype4COM object:
$oSkype = ObjCreate("Skype4COM.Skype")

;// Start the Skype client:
If Not $oSkype.Client.IsRunning Then
    $oSkype.Client.Start()
    While 1
        If Not $oSkype.Client.IsRunning Then
    Do
        $ObjError = 0
        $pSkype.Attach
        Until NOT $ObjError
        $ObjError = 0
        Else
            ExitLoop
        EndIf
    WEnd
EndIf


;// When attached to the API, send repeated commands to the API to test if they succeed:
While 1
  Sleep(1000)
  If $oSkype.AttachmentStatus = $oSkype.Convert.TextToAttachmentStatus("SUCCESS") Then
    MsgBox(0,"","PING..")
    $oSkype.SendCommand($oSkype.Command(0, "PING","PONG",TRUE))
    Skype_AttachmentStatus()
  EndIf
WEnd

;// The AttachmentStatus event handler monitors attachment status and returns the Skypename of the user when the status is "success":
Func Skype_AttachmentStatus()
    $aStatus = $oSkype.AttachmentStatus
    MsgBox(0,"Attachment status",$oSkype.Convert.AttachmentStatusToText($aStatus))
    If $aStatus = $oSkype.Convert.TextToAttachmentStatus("AVAILABLE") Then
        $oSkype.Attach()
    EndIf
    If $aStatus = $oSkype.Convert.TextToAttachmentStatus("SUCCESS") Then
        MsgBox(0,"","Current user is " & $oSkype.CurrentUserHandle)
    EndIf  
EndFunc

; This is my custom error handler 
Func ObjErrorHandler() 
   $HexNumber=hex($ObjErrorObj.number,8) 
   Msgbox(0,"","We intercepted a COM Error !" & @CRLF & _
                "Number is: " & $HexNumber & @CRLF & _
                "Windescription is: " & $ObjErrorObj.windescription ) 
   $ObjError = 1 ; something to check for when this function returns
Endfunc
Edited by vanowm
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...