Function InitLog add

Function InitLog add

#region ====INIT ===============================================================
	Func _ConfigInitial()
;~ 		ConsoleWrite('++ConfigDBInitial() = ' & @CRLF)
		_SQLite_down()
;~ 		_DBvarInit()
		; -------check if SQLIte SubteBA db exist
		SQLite_init()
		$SQLq = "SELECT name FROM sqlite_temp_master WHERE type='table';"
		_SQLITErun($SQLq, $dbfullPath, $quietSQLQuery)
	;~ 	;-------- Init Log
	 	_initLog()
		;------------------------------------------------------------------------------
	EndFunc   ;==>_ConfigDBInitial
#endregion
#region  ==== SQL functions =======================================================================
	Func SQLInsertMessage($TweetID,$TweeMsg,$TweeDate)
;~ 		ConsoleWrite('++InsertMessageSQL() = '& @crlf)
		$query='INSERT INTO messages VALUES (' & $TweetID & ',"' & $TweeMsg & '" ,' & $TweeDate & ') ;'
		if _SQLITErun($query,$dbfullPath,$quietSQLQuery) Then
			return true
		Else
			MsgBox(48+4096,"Error inserting mesages ErrNo 1010" & @CRLF & $query,0,0)
			Return false
		EndIf
	EndFunc
	Func SQLInsertUserMessage($TweetID,$TweeMsg,$UserID,$Fname,$Lname,$TweeDate)
;~ 		ConsoleWrite('++InsertMessageSQL() = '& @crlf)
		$query='INSERT INTO UserMessages VALUES (' & $TweetID & ',"' & _
		$TweeMsg & '" ,' & $UserID & ',"' & $Fname &"_"& $Lname & '",' & $TweeDate & ') ;'
		if _SQLITErun($query,$dbfullPath,$quietSQLQuery) Then
			return true
		Else
			MsgBox(48+4096,"Error inserting mesages ErrNo 1010" & @CRLF & $query,0,0)
			Return false
		EndIf
	EndFunc
	Func SQLGetUsers()
;~ 		ConsoleWrite('++SQLGetUsers() = '& @crlf)
		$query='SELECT * FROM Users ;'
		_SQLITEqry($query,$dbfullPath)
	EndFunc
	Func SQLGetActiveUsers()
;~ 		ConsoleWrite('++SQLGetActiveUsers() = '& @crlf)
		$query='SELECT * FROM Users WHERE Active=1 ;'
		_SQLITEqry($query,$dbfullPath)
	EndFunc
	Func SQLGetDevUsers()
;~ 		ConsoleWrite('++SQLGetDevUsers() = '& @crlf)
		$query='SELECT * FROM Users WHERE Active=1 AND Dev=1 ;'
		_SQLITEqry($query,$dbfullPath)
	EndFunc
	Func SQLExist_Message($TweetID)
;~ 		ConsoleWrite('++Exist_Message() = '&$TweetID& @crlf)
		$query='SELECT id FROM messages WHERE id="'&$TweetID &'";'
		_SQLITEqry($query,$dbfullPath)
		If  IsArray($qryResult) Then
			if UBound($qryResult)>1 then
				return $qryResult[1][0]
			EndIf
			return 0
		endif
		Return 0
	EndFunc
#endregion
#region  ==== send messages =======================================================================
	Func TelegramInitialMessage($UserID)
;~ 	ConsoleWrite('++TelegramInitialMessage() = '& @crlf)
		$message ="SubteBA BOT , lee los informes de Subte BA en Twitter, y los manda por este canal. "
		$message&='Este canal no es official del subte de Buenos Aires Ni de Metrovias.'  & $nuevaLinea
		$message&= $nuevaLinea
		$message&='Commandos:'  & $nuevaLinea
		$message&='/START -> Activa alertas. '  & $nuevaLinea
		$message&='/STOP  -> Desactiva alertas. '  & $nuevaLinea
		$message&='/INFO   -> Este mensaje'  & $nuevaLinea
		$message&= $nuevaLinea
		$message&='Futuros Comandos:'  & $nuevaLinea
		$message&='/ACTIVAR -> Alertas de lineas elegidas.'  & $nuevaLinea
		$message&='/DESACTIVAR -> Alertas de lineas elegidas.'  & $nuevaLinea
		$message&='/CERCANA -> Estacion mas cercana.'  & $nuevaLinea
		$message&='/ESTACIONES -> lista de estaciones por linea.'  & $nuevaLinea
		$message&='/HORARIOS -> Horarios de actividad'  & $nuevaLinea
		$message&='/MAPA -> Mapa de lineas de subte'  & $nuevaLinea
		$message&='/PROPUESTA -> Enviar propuestas'  & $nuevaLinea

		$respuesta = SendTelegramexec($UserID,$message)
		return $respuesta
	EndFunc
	Func TelegramSTOPMessage($UserID)
		$message ="Los mensajes de alertas han sido deshabilitados" & $nuevaLinea
		$message&='/START -> Para habilitar la recepcion de alertas'  & $nuevaLinea
		$message&='/INFO -> para mas informacion.'  & $nuevaLinea

		$respuesta = SendTelegramexec($UserID,$message)
		return $respuesta
	EndFunc
	Func TelegramSTARTMessage($UserID)
		$message ="Los mensajes de alertas han sido habilitados" & $nuevaLinea
		$message&='/STOP-> Para deshabilitar la recepcion de alertas'  & $nuevaLinea
		$message&='/INFO -> para mas informacion.'  & $nuevaLinea

		$respuesta = SendTelegramexec($UserID,$message)
		return $respuesta
	EndFunc
	Func TelegramErrorMessage($UserID)
		$message ="No se ha registrado el cambio requerido." & $nuevaLinea
		$message&='Reintente enviar el comando nuevamente.'  & $nuevaLinea
		$message&='INFO -> para mas informacion.'  & $nuevaLinea

		$respuesta = SendTelegramexec($UserID,$message)
		return $respuesta
	EndFunc
	Func TelegramBaseMessage($TweetID,$USRmsg,$UserID,$Fname,$Lname,$epoch)
		$message ="No logro entender el mensaje."
		$message&='Reintente enviar el comando nuevamente.'  & $nuevaLinea
		$message&='/INFO -> para mas informacion.'& $nuevaLinea & $nuevaLinea
;~ 		$message&="Su mensage:" & $nuevaLinea & $USRmsg
		$respuesta = SendTelegramexec($UserID,$message)
		SQLInsertUserMessage($TweetID,$USRmsg,$UserID,$Fname,$Lname,$epoch)
		return $respuesta
	EndFunc
	Func TelegramInformNewUser($UserID,$Fname,$Lname)
		$message ="Nunevo usuario:" & $nuevaLinea
		$message&=$Fname & "  " & $Lname
		$respuesta = SendTelegramexec($UserID,$message)
		return $respuesta
	EndFunc
	Func TelegramLocationMessage($TweetID,$USRmsg,$UserID,$Fname,$Lname,$epoch)
		$message ="La Funcion de Informacion sobre las estaciones mas cercanas "
		$message&='No esta implementado en este momento.'  & $nuevaLinea
		$message&='/INFO -> para mas informacion.'& $nuevaLinea & $nuevaLinea
;~ 		$message&="Su mensage:" & $nuevaLinea & $USRmsg
		$respuesta = SendTelegramexec($UserID,$message)
		SQLInsertUserMessage($TweetID,$USRmsg,$UserID,$Fname,$Lname,$epoch)
		return $respuesta
	EndFunc
	Func TelegramActivateMessage($TweetID,$USRmsg,$UserID,$Fname,$Lname,$epoch)
		$message ="La Funcion de Activacion de alertas por linea, "
		$message&='No esta implementado en este momento.'  & $nuevaLinea
		$message&='/INFO -> para mas informacion.'& $nuevaLinea & $nuevaLinea
;~ 		$message&=$USRmsg& $nuevaLinea
;~ 		$message&="Su mensage:" & $nuevaLinea & $USRmsg
		$respuesta = SendTelegramexec($UserID,$message)
		SQLInsertUserMessage($TweetID,$USRmsg,$UserID,$Fname,$Lname,$epoch)
		return $respuesta
	EndFunc
	Func ReformatMessage($message)
;~ 	ConsoleWrite('++ReformatMessage() = '& @crlf)
		$msgArr=StringSplit($message,"Actualizado",1)
		$diaHoraArr=stringsplit(StringStripWS($msgArr[2],1+2)," ")
		$hora=$diaHoraArr[2]
		$dia=$diaHoraArr[1]
		$msg=""&$hora&""&"     " & $dia & $nuevaLinea & StringStripWS($msgArr[1],1+2)
		return $msg
	EndFunc
	Func sendmessages($message)
		$message=ReformatMessage($message)
		SQLGetActiveUsers()
		If  IsArray($qryResult) Then
			for $i=1 to UBound($qryResult)-1
				$isDev = $qryResult[$i][4]
				$chatid = $qryResult[$i][0]
				$ChatUser = $qryResult[$i][1] & " " & $qryResult[$i][2]
				if $chatID<>"" then
					select
						Case $SendToAll = 1
							ConsoleWrite('- $chatid = ' & $chatid & "  ->  " & $ChatUser & @CRLF)
							$respuesta = SendTelegramexec($chatid,$message)
						Case $isDev = 1 AND $SendToAll = 0
							ConsoleWrite('- $chatid = ' & $chatid & "  ->  " & $ChatUser & @CRLF)
							$respuesta = SendTelegramexec($chatid,$message)
					endSelect
					;~ $respuesta  0 is ok
				endif
			next
			return true
		endif
		Return false
	EndFunc   ;==>_sendmessages
	Func SendTelegramexec($chatid,$msgtext="testeo harcoded",$DisableNotification=True)
		$urlMSG="https://api.telegram.org/" & $token & "/sendMessage?chat_id=" & $chatid & _
		"&text=" & $msgtext & "&parse_mode=HTML"
		If $DisableNotification = True Then $urlMSG &= "&disable_notification=True"
		$sGet = HttpGet($urlMSG)

		if $sget<>"0"  then
			ConsoleWrite('Tlgm sent = ' & $msgtext & @crlf )
			return 0
		Else
			$s_text="Error sending message to Telegram = " & $sGet
			ConsoleWrite('!! ' & $s_text & @crlf )
			return 1
		endif
	EndFunc
#endregion
#region  ==== Tweeter scrapping ===================================================================
	Func TweeterMessages($Username)
		ConsoleWrite('++TweeterMessages() = '& $Username &@crlf)
		$htmltxt=_ScrapTweetMessages($Username)
		if $htmltxt<>"" then
			$TweetArr = _gettweetArr($htmltxt)
			if IsArray($TweetArr) then
				$newMessagesFlag=0
				_ArraySort($TweetArr, 0, 0, 0, 2)
				For $i = 0 To UBound($TweetArr) -1
					$TweetID = $TweetArr[$i][0]
					$TweeMsg = $TweetArr[$i][1]
					$TweeDate = $TweetArr[$i][2]
					if not SQLExist_Message($TweetID) then
						SQLInsertMessage($TweetID,$TweeMsg,$TweeDate)
						$TweetMinOld= (_GetUnixTime() - $TweeDate)/60
						if $TweetMinOld < 60 then
							sendmessages($TweeMsg)
							$newMessagesFlag=1
							ConsoleWrite('+ New messages ' & _NowTime(4) & "   ")
						Else
							ConsoleWrite('+ Old messages ' & Sec2Time($TweetMinOld*60) & @crlf)
						endif
					endif
					sleep(2000)
				Next
				if $newMessagesFlag=0 then ConsoleWrite('  No new messages ' & _NowTime(4) & @CRLF)
			endif
		endif
	EndFunc
	func _ScrapTweetMessages($Username)
		Local $sData = InetRead("https://twitter.com/"&$Username)
		Local $nBytesRead = @extended
		ConsoleWrite('@@ BytesRead = ' & $nBytesRead &"   ")
		$htmltxt = BinaryToString($sData)
		If $nBytesRead < 100000 or StringInStr($htmltxt,"subteba")<1 Then
			ConsoleWrite('  Connection issue contacting  ' & "https://twitter.com/"&$Username& @crlf)
			$htmltxt=""
			Return $htmltxt
		endif
		return $htmltxt
	EndFunc
	Func _gettweetArr($htmltxt)
		$MSGArr = StringRegExp($htmltxt, '(?s)(?i)
(.*?)
', 3)
		if IsArray($MSGArr) then
			dim  $TweetMSGArr[UBound($MSGArr)]
			For $i = 0 To UBound($MSGArr) -1
				$TweetMessage = StringRegExp($MSGArr[$i], '(?s)(?i)
(.*?)
', 1)
				$mensaje = clearstring($TweetMessage[1])
				$TweetMSGArr[$i]=$mensaje
			Next
			$TweetDate = StringRegExp($htmltxt, '(?s)(?i)data-time="(.*?)"', 3)
			$TweetIDArr = StringRegExp($htmltxt, '(?s)(?i)data-tweet-id="(.*?)"', 3)
			$TweetArrAux = _mergeArray($TweetIDArr, $TweetMSGArr)
			$TweetArr = _mergeArray($TweetArrAux, $TweetDate)
			return $TweetArr
		Else
			ConsoleWrite('!!!(' &  @ScriptLineNumber & ') : Error on  $MSGArr = ' & $MSGArr & @crlf )
			return 0
		endif
	EndFunc
#endregion
#region  ==== Bot Messages handeling ===================================================================
	Func Get_BotOffSet()
;~ 		ConsoleWrite('++Get_BotOffSet() = '& @crlf)
		if NOT FileExists($OffsetFile) then
			$fileh = FileOpen($OffsetFile,1+8)
			If $fileh = -1 Then
				ConsoleWrite('   "Unable to open file 1.' & $OffsetFile )
				return 0
			endif
			FileClose($fileh)
		EndIf
		$fileh = FileOpen($OffsetFile,0)
		If $fileh = -1 Then
			ConsoleWrite('   "Unable to open file 2.' & $OffsetFile )
			return 0
		endif
		Local $offset = FileReadLine($fileh)
		if @error = -1 Then
			FileClose($fileh)
			return 0
		endif
		ConsoleWrite("Get OffSet:"& $offset)
		FileClose($fileh)
		return $offset
	EndFunc
	Func Set_BotOffSet($offset)
		ConsoleWrite('++Set_BotOffSet() = '&$offset& @crlf)
		if NOT FileExists($OffsetFile) then
			$fileh = FileOpen($OffsetFile,1+8)
			If $fileh = -1 Then
				ConsoleWrite('   "Unable to open file 3.' & $OffsetFile )
				return 0
			endif
			FileClose($fileh)
		EndIf
		$fileh = FileOpen($OffsetFile,2)
		If $fileh = -1 Then
			ConsoleWrite('   "Unable to open file 4.' & $OffsetFile )
			return 0
		endif
		FileWriteLine($fileh,$offset)
		if @error = -1 Then
			FileClose($fileh)
			return 0
		endif
		ConsoleWrite("    Set OffSet:"& $offset &@crlf)
		FileClose($fileh)
		return 1
	EndFunc
	func UpdateUsers()
		ConsoleWrite('  '&@HOUR & ':' & @MIN&  ':' & @sec & '  Update users.  ' )
		local $s=GetBotUpdates()
		if $s then
			initMsgClass()
			$s=ParseForUserUpdate($s)
;~ 			ConsoleWrite('  $s = ' & $s & @crlf )
			if $s then
				$oJSON = _OO_JSON_Init()
				$jsonObj = $oJSON.parse($s)
				if $jsonObj.ok  then
					if $jsonObj.jsonPath( "$.result").stringify() = "[[]]" then
						ConsoleWrite(' No Bot data ' & @crlf)
					Else
						ConsoleWrite('  Updating... ' & @crlf)
						$UpdateIDArr = StripIntJS($jsonObj.jsonPath( "$.result..update_id").stringify()  )
						$MSGIDArr =    StripIntJS($jsonObj.jsonPath( "$.result..message.message_id").stringify())
						$UserIDArr =   StripIntJS($jsonObj.jsonPath( "$.result..message.from.id").stringify())
						$FnameArr =    StripStrJS($jsonObj.jsonPath( "$.result..message.from.first_name").stringify())
						$LnameArr =    StripStrJS($jsonObj.jsonPath( "$.result..message.from.last_name").stringify())
						$ChatIDArr =   StripIntJS($jsonObj.jsonPath( "$.result..message.chat.id").stringify())
						$ChatFnameArr =    StripStrJS($jsonObj.jsonPath( "$.result..message.from.first_name").stringify())
						$ChatLnameArr =    StripStrJS($jsonObj.jsonPath( "$.result..message.from.last_name").stringify())
						$epochArr =    StripIntJS($jsonObj.jsonPath( "$.result..message.date").stringify())
						$menssageArr = StripStrJS($jsonObj.jsonPath( "$.result..message.text").stringify())
						$IsBot =       StripIntJS($jsonObj.jsonPath( "$.result..message.from.is_bot").stringify())

						if $UserIDArr[0] = $UpdateIDArr[0] AND  $UserIDArr[0] = $FnameArr[0] AND _
							$UserIDArr[0] = $LnameArr[0]    AND  $UserIDArr[0] = $epochArr[0] AND _
							$UserIDArr[0] = $menssageArr[0] AND  $UserIDArr[0] = $IsBot[0]  then
							$retBad=0
							for $i=1 to $UserIDArr[0]
								if $IsBot[$i] <> "true" then
									$ret=SQLregister($UserIDArr[$i],$FnameArr[$i],$LnameArr[$i],$epochArr[$i],$menssageArr[$i])
									$ret1=ParseBotMessage($UserIDArr[$i],$FnameArr[$i],$LnameArr[$i],$epochArr[$i],$menssageArr[$i],$UpdateIDArr[$i],$MSGIDArr[$i])
									ConsoleWrite('>> $ret1 = ' & $ret1 & @crlf )
									if (Not $ret) or (Not $ret1)  then	$retBad+=1
									$UpdateID=$UpdateIDArr[$i]
								Else
									ConsoleWrite('+(' & @ScriptLineNumber & ') : $menssageArr[$i] = ' & $menssageArr[$i] & @crlf )
									ConsoleWrite('+(' & @ScriptLineNumber & ') : $IsBot[$i] = ' & $IsBot[$i] & @crlf )
									if AImessage($menssageArr[$i],"callback_query") then
										if AImessage($menssageArr[$i],"CLOSE_O") then
											$ahora=1
											TelegramActivateMessage($UpdateIDArr[$i],$menssageArr[$i],$ChatIDArr[$i],$ChatFnameArr[$i],$ChatLnameArr[$i],$epochArr[$i])
											_DeleteMsg($ChatIDArr[$i], $MSGIDArr[$i])
											$KeyBoardActive=0
										else
											$ret=SQLUpdateUserAlerts($ChatIDArr[$i],$menssageArr[$i])
											if not $ret then $retBad=1
											$ahora=0.2
										endif
										$UpdateID=$UpdateIDArr[$i]
									Else
										$retBad=1
									endif
								endif
							next
							if $retBad=0 then Set_BotOffSet($UpdateID+1)
						Else
							_printFromArray($ChatIDArr,"$ChatIDArr")
							_printFromArray($ChatFnameArr,"$ChatFnameArr")
							_printFromArray($ChatLnameArr,"$ChatLnameArr")
							_printFromArray($MSGIDArr,"$MSGIDArr")
							_printFromArray($UserIDArr,"UserIDArr")
							_printFromArray($FnameArr,"FnameArr")
							_printFromArray($LnameArr,"LnameArr")
							_printFromArray($epochArr,"epochArr")
							_printFromArray($menssageArr,"menssageArr")
							_printFromArray($UpdateIDArr,"UpdateIDArr")
							_printFromArray($IsBot,"IsBot")
							ConsoleWrite('  Error in JS array . exiting..... ' & @crlf)
							exit 29
						endif
					endif
				endif
			endif
		endif
		if $KeyBoardActive=1 or $KeyboardCheckcount > 5 then
			ClearKeyBoards()
			$KeyboardCheckcount = 0
		Else
			$KeyboardCheckcount = $KeyboardCheckcount +1
		endif
		ConsoleWrite('**(' & @ScriptLineNumber & ') : $KeyBoardActive= ' & $KeyBoardActive &@crlf )
	EndFunc
	Func GetBotUpdates()
		$offset=Get_BotOffSet()
		$urlMSG="https://api.telegram.org/" & $token & "/getUpdates?offset="&$offset
		$sGet = HttpGetJson1($urlMSG)
;~ 		ConsoleWrite('@@ $sGet = ' & $sGet & @crlf )
		if $sGet<>"" then
			return $sGet
		Else
			$s_text="  Error getUpdates from Telegram = "
			ConsoleWrite('!! ' & $s_text & @crlf & "! " & $sGet)
			return false
		endif
	EndFunc
	Func StripStrJS($st)
		$st=StringReplace($st,'","',":::")
		$st=clearstring($st)
		$st=StringReplace($st,"[","")
		$st=StringReplace($st,"]","")
		$st=StringReplace($st,'"',"")
		$stArr=StringSplit($st,":::",1)
		return $stArr
	EndFunc
	Func StripIntJS($st)
		$st=StringReplace($st,',',":::")
		$st=clearstring($st)
		$st=StringReplace($st,"[","")
		$st=StringReplace($st,"]","")
		$st=StringReplace($st,'"',"")
		$stArr=StringSplit($st,":::",1)
		return $stArr
	EndFunc
	Func ParseForUserUpdate($s)
;~ 		eliminate "edited_message":{"
		$s=StringReplace($s,'"edited_message":{','"message":{')

;     check lastname
		$LNarr=StringRegExp($s,'"first_name":"(.*?)","language_code":"',1)
		if IsArray($LNarr) then
			for $r=0 to UBound($LNarr)-1
				$donde='"first_name":"[a-zA-Z]*","language_code":"'
				$pat='"first_name":"' & $LNarr[$r] & '","last_name":"xxx","language_code":"'
				$s=StringRegExpReplace($s,$donde,$pat)

				$donde='"first_name":"[a-zA-Z]*","type":"'
				$pat='"first_name":"' & $LNarr[$r] & '","last_name":"xxx","type":"'
				$s=StringRegExpReplace($s,$donde,$pat)
			next
		endif

;~ 		eliminate "callback_query":{"
		if StringInStr($s,'"callback_query":')> 0 then
			$s=StringRegExpReplace($s,'(?s)(?i)"callback_query":(.*?)"from":(.*?)},',"")
			$s=StringRegExpReplace($s,'},"chat_instance":"(.*?)"',"")
			$s=StringRegExpReplace($s,',"text":"(.*?)",',",")
			$s=StringRegExpReplace($s,',"data":"',',"text":"callback_query ')
		endif
;~ 		eliminate location info
;~ "location":{"latitude":-34.631010,"longitude":-58.469731}}
		if StringInStr($s,'"location":{')> 0 then
			$MsgClass[0]="Location"
				$posini=StringInStr($s,'{"latitude":')+12
				$posend=StringInStr($s,'"longitude":')-$posini-1
			$MsgClass[1]=StringMid($s,$posini,$posend)
				$posini=StringInStr($s,'"longitude":')+12
			$MsgClass[2]=StringMid($s,$posini,$posend)
			$s=StringRegExpReplace($s,'(?s)(?i)"location":{"latitude":(.*?),"longitude":(.*?)}' , '"text": "' & $MsgClass[0] & ":" & $MsgClass[1] & ":" & $MsgClass[2] & '"' )
		endif

;~ 		eliminate contact info
		$s=StringRegExpReplace($s,'(?s)(?i)"contact":(.*?)}'  ,  '"text": ""' )

;~ 		eliminate photo info
		$s=StringRegExpReplace($s,'(?s)(?i)"photo":\[(.*?)\]'  ,  '"text": ""' )

;~ 		replace username last-name
		$s=StringReplace($s,'"username":','"last_name":')

;~ 		eliminate sticker info
		$s=StringRegExpReplace($s,'(?s)(?i)"sticker":(.*?)}(.*?)}'  ,  '"text": ""' )
		return $s
	EndFunc
	Func SQLregister($UserID,$Fname,$Lname,$epoch,$mensage)
;~ 	ConsoleWrite('++SQLregister() = '& @crlf)
		$existUser=0
		If SQLExistUser($UserID)=$userID then $existUser=1
		if $existUser=0 then
			$setactive=1
			$ret=SQLInsertUser($UserID,$Fname,$Lname,$epoch,$setactive)
			if $ret then
				TelegramInformNewUser($DEVChatID,$Fname,$Lname)
				$ret=TelegramSTOPMessage($UserID)
				if $ret=0 then return true
			else
				$ret=TelegramErrorMessage($UserID)
				if $ret=0 then return true
			endif
			return false
		endif

		$setactive=-1
		if AIMessage($mensage,"/START") then $setactive=1
		if AIMessage($mensage,"/STOP") then $setactive=0
		if $existUser=1 AND $setactive<>-1 then
			$ret=SQLUpdateUserActive($UserID,$Fname,$Lname,$setactive)
			if $ret and $setactive=0 then
				$ret=TelegramSTOPMessage($UserID)
				if $ret=0 then return true
			endif
			if $ret and $setactive=1 then
				$ret=TelegramSTARTMessage($UserID)
				if $ret=0 then return true
			endif
			if NOT $ret then TelegramErrorMessage($UserID)
			return false
		endif

		return true
	EndFunc
	Func SQLInsertUser($UserID,$Fname,$Lname,$epoch,$active=1)
		ConsoleWrite('  Nuevo usuario = '& $Fname & "  "  & $Lname  & @crlf)
		$query='INSERT INTO Users VALUES (' & $UserID & ',"' & $Fname & '","' & $Lname & '",' & $active &',0,' & $epoch & ') ;'
		if _SQLITErun($query,$dbfullPath,$quietSQLQuery) Then
			return true
		Else
			MsgBox(48+4096,"Error inserting User ErrNo 1011" & @CRLF & $query,0,0)
			Return false
		EndIf
	EndFunc
	Func SQLUpdateUserActive($UserID,$Fname,$Lname,$active=1)
		ConsoleWrite('    Usuario Activo 1/Start 0/Stop= '&$active& "  " & $Fname & "  "  & $Lname  & @crlf)
		$query='UPDATE  Users SET Active=' & $active &' WHERE UserID='& $UserID & ' ;'
		if _SQLITErun($query,$dbfullPath,$quietSQLQuery) Then
			return true
		Else
			ConsoleWrite("       Error updating active user User ErrNo 1012" & @CRLF & $query& @crlf)
			Return false
		EndIf
	EndFunc
	Func SQLExistUser($UserID)
;~ 	ConsoleWrite('++SQLExistUser() = '& @crlf)
		$query='SELECT UserID FROM Users WHERE UserID="'&$UserID &'";'
		_SQLITEqry($query,$dbfullPath)
		If  IsArray($qryResult) Then
			if UBound($qryResult)>1 then
				return $qryResult[1][0]
			EndIf
			return 0
		endif
		Return 0
	EndFunc
	Func SQLUpdateUserAlerts($UserID,$mensage,$active=1)
		$mensage=StringReplace($mensage,"callback_query ","")
		$msgArr=StringSplit($mensage,"_")
		_printfromarray($msgArr)
		if $msgArr[2]="ON" then
			$query='UPDATE AlertasLineas SET ' & $msgArr[1] & '=1 WHERE userid=' & $UserID & ';   '
			$query&='INSERT INTO AlertasLineas (userid,' & $msgArr[1] & ')  SELECT ' & $UserID & ',1 WHERE (Select Changes() = 0);'
			if _SQLITErun($query,$dbfullPath,$quietSQLQuery) Then
				return true
			Else
				ConsoleWrite("!    Error updating alertasLineas User ErrNo 1013" & @CRLF & $query& @crlf)
				Return false
			EndIf
		endif
	EndFunc
#endregion
#region   ===================================   keyboard   ==========================
	;============== show keyboard =========================
	func KeyboardActivate($UserID)
		$keybrd =  '{"inline_keyboard":['
		$keybrd &= '['
		$keybrd &= '{"text":"Linea A","callback_data":"A_ON"},'
		$keybrd &= '{"text":"Linea B","callback_data":"B_ON"},'
		$keybrd &= '{"text":"Linea C","callback_data":"C_ON"}'
		$keybrd &= '],['
		$keybrd &= '{"text":"Linea D","callback_data":"D_ON"},'
		$keybrd &= '{"text":"Linea E","callback_data":"E_ON"},'
		$keybrd &= '{"text":"Linea H","callback_data":"H_ON"}'
		$keybrd &= '],['
		$keybrd &= '{"text":"Linea P","callback_data":"P_ON"},'
		$keybrd &= '{"text":"Linea U","callback_data":"U_ON"},'
		$keybrd &= '{"text":"Listo","callback_data":"CLOSE_ON"}'
		$keybrd &= '],['
		$keybrd &= ']'
		$keybrd &= ']}'
		$res=_SendMsg($UserID,"Sus alertas activas son:"& "" & $nuevaLinea & "Cual desea activar?","HTML",$keybrd)
		$MSGID=StringRegExp($res,'"message_id":(.*?),"from":',1)
		$UsrID=StringRegExp($res,',"chat":{"id":(.*?),"first_name":',1)
		$utime=StringRegExp($res,',"date":(.*?),"text":',1)
		if IsArray($MSGID) then	SQLregisterKeyboard($UsrID[0],$MsgID[0],$utime[0])
		if $res then return True
		return false
	EndFunc
	func KeyboardDesActivate($UserID)
		$keybrd =  '{"inline_keyboard":['
		$keybrd &= '['
		$keybrd &= '{"text":"Linea A","callback_data":"A_OFF"},'
		$keybrd &= '{"text":"Linea B","callback_data":"B_OFF"},'
		$keybrd &= '{"text":"Linea C","callback_data":"C_OFF"}'
		$keybrd &= '],['
		$keybrd &= '{"text":"Linea D","callback_data":"D_OFF"},'
		$keybrd &= '{"text":"Linea E","callback_data":"E_OFF"},'
		$keybrd &= '{"text":"Linea H","callback_data":"H_OFF"}'
		$keybrd &= '],['
		$keybrd &= '{"text":"Linea P","callback_data":"P_OFF"},'
		$keybrd &= '{"text":"Linea U","callback_data":"U_OFF"},'
		$keybrd &= '{"text":"Listo","callback_data":"CLOSE_OFF"}'
		$keybrd &= '],['
		$keybrd &= ']'
		$keybrd &= ']}'
		$res=_SendMsg($UserID,"Sus alertas activas son:"& "" & $nuevaLinea & "Cual desea desactivar?","HTML",$keybrd)
		$MSGID=StringRegExp($res,'"message_id":(.*?),"from":',1)
		$UsrID=StringRegExp($res,',"chat":{"id":(.*?),"first_name":',1)
		$utime=StringRegExp($res,',"date":(.*?),"text":',1)
		if IsArray($MSGID) then	SQLregisterKeyboard($UsrID[0],$MsgID[0],$utime[0])
		if $res then return True
		return false
	EndFunc
	Func SQLregisterKeyboard($UserID,$MsgID,$epoch)
		$query='INSERT INTO Keyboard VALUES (' & $UserID & ',' & $MsgID  & ',' & $epoch & ') ;'
		if _SQLITErun($query,$dbfullPath,$quietSQLQuery) Then
			$KeyBoardActive=1
			$ahora=0.2
			return true
		endif
		Return false
	EndFunc
	;==================   limpiar keyboard  =====================
	Func ClearKeyBoards()
		ConsoleWrite('**(' & @ScriptLineNumber & ') : ClearKeyBoards()  $KeyBoardActive= ' & $KeyBoardActive &@crlf )
		$query='SELECT UserID,MsgID FROM Keyboard WHERE Timestamp < ' & _GetUnixTime()-60 & ';'
		_SQLITEqry($query,$dbfullPath)
;~ 		$ahora=0.2
		If  IsArray($qryResult) Then
			if UBound($qryResult)>1 then
				for $i=1 to UBound($qryResult)-1
					_printFromArray($qryResult)
					ConsoleWrite('**@@(' & @ScriptLineNumber & ') : $i = ' & $i & @crlf )
					_DeleteMsg( $qryResult[$i][0],$qryResult[$i][1])
					SQLUnRegisterKeyboard($qryResult[$i][0],$qryResult[$i][1])
					$ahora=1
				next
			EndIf
		endif
	EndFunc
	Func SQLUnRegisterKeyboard($UserID,$MsgID)
		$query='DELETE FROM Keyboard WHERE UserID=' & $UserID & ' AND MsgID=' & $MsgID & ' ;'
		if _SQLITErun($query,$dbfullPath,$quietSQLQuery) Then return true
		Return false
	EndFunc
#endregion
#region   ===========================================================================
	func closeall()
		_SQLite_Close()
		_SQLite_Shutdown()
		exit 30
	EndFunc
#endregion
#region =====================================   Helpers functions  ===============================
	Func _mergeArray($array1, $array2)
		$array1 = _ArrayAdd_Column($array1)
		$size = UBound($array1)
		$newCol = UBound($array1, 2) - 1
		For $i = 0 To $size - 1
			$array1[$i][$newCol] = $array2[$i]
		Next
		Return $array1
	EndFunc   ;==>_mergeArray
	Func _ArrayAdd_Column($Array)
		Local $aTemp[UBound($Array)][UBound($Array, 0) + 1]
		For $i = 0 To UBound($Array) - 1

			For $j = 0 To UBound($Array, 0) - 1
				If UBound($Array, 0) = 1 Then $aTemp[$i][0] = $Array[$i]
				If UBound($Array, 0) > 1 Then $aTemp[$i][$j] = $Array[$i][$j]
			Next
		Next
		Return $aTemp
	EndFunc   ;==>_ArrayAdd_Column
	Func _ClearSciteConsole()
		ConsoleWrite('!!!!!!!!!!!_ClearSciteConsole Func General 92!!!!!!!!!!!!  ' & @CRLF)
		ControlSend("[CLASS:SciTEWindow]", "", "Scintilla2", "+{F5}")
	EndFunc   ;==>_ClearSciteConsole
	Func _GetDOSOutput($sCommand)
	 ConsoleWrite('++_GetDOSOutput $sCommand = ' & $sCommand & @crlf )
		Local $iPID, $sOutput = ""
		$iPID = Run('"' & @ComSpec & '" /c ' & $sCommand, "", @SW_HIDE, 2 + 4)
		While 1
			$sOutput &= StdoutRead($iPID, False, False)
			$err=@error
			If $err Then
				ConsoleWrite('!!  _GetDOSOutput $err = ' & $err & @crlf )
				ExitLoop
			EndIf
	;~ 	Sleep(10)
		WEnd
		ConsoleWrite('>> 	Output = ' & $sOutput & @crlf )
		Return $sOutput
	EndFunc   ;==>_GetDOSOutput
	Func _timeBetween($cTime, $sTime, $eTime)
		 If Not _DateIsValid('2000/01/01 ' & $cTime) Then Return -1
		 If Not _DateIsValid('2000/01/01 ' & $sTime) Then Return -2
		 If Not _DateIsValid('2000/01/01 ' & $eTime) Then Return -3
		 If _DateDiff('s', '2000/01/01 ' & $cTime & ':00', '2000/01/01 ' & $sTime & ':00') < 0 And _
			 _DateDiff('s', '2000/01/01 ' & $cTime & ':00', '2000/01/01 ' & $eTime & ':00') > 0 Then
			  Return 1
		 Else
			  Return 0
		 EndIf
	EndFunc  ; ==>_timeBetween
#endregion
#region log
	Func _initLog()
		ConsoleWrite('++_initLog() = '& @crlf)
		FileClose($hLogFile)
		;open log file for activity
		$hLogFile = FileOpen($LogFileActivity, 1+8)
		If $hLogFile = -1 Then
			ConsoleWrite("Error Unable to open file Log File.")
			MsgBox(48+4096, "Activity Log File error", "Activity Log File cannot be reached." & @crlf & _
								"File configured: " & $LogFileActivity & @crlf & _
								"Using Log file: " & $LogFileActivity& @crlf &"ErrNo 2052",0)
		EndIf

		ConsoleWrite('- ActivityLogFile = ' & $LogFileActivity & @crlf )
		FileWriteLine($hLogFile,"===============================================================================" )
		FileWriteLine($hLogFile,"===============================================================================")
		FileWriteLine($hLogFile,_NowCalcDate()  & @TAB& "Start of activities"& @TAB& "Version: "& $version)
		FileWriteLine($hLogFile,"===============================================================================")
	EndFunc
	Func _ConsoleWrite($s_text,$logLevel=0)
		Switch $logLevel
			Case 0
				$logLevelmsg="DEBUG"
				$levelcolor="+"
			Case 1
				$levelcolor=">"
				$logLevelmsg="INFO"
			Case 2
				$levelcolor="-"
				$logLevelmsg="WARN"
			Case 3
				$levelcolor="!"
				$logLevelmsg="ERROR"
			Case Else
				$logLevelmsg="NA"
		EndSwitch
		FileWriteLine($hLogFile, _LogDate()&" ["& $logLevelmsg&"] " & $s_text )
;~ 			ConsoleWrite($levelcolor&"["& $logLevelmsg&"] " & $s_text & @CRLF)
		ConsoleWrite($s_text & @CRLF)
	EndFunc   ;==>_ConsoleWrite
	Func _LogDate()
		$tCur = _Date_Time_GetLocalTime()
		$tCur = _Date_Time_SystemTimeToDateTimeStr($tCur)
		$date = "[" & stringreplace($tCur,"/","-") & "] "
		return $date
	EndFunc
	Func _EndLog()
		ConsoleWrite('++_EndLog() = '& @crlf)
		FileWriteLine($hLogFile,"..............................................................................." )
		FileWriteLine($hLogFile,_NowCalcDate()   & @TAB& "End of activities")
		FileWriteLine($hLogFile,"..............................................................................." & @CRLF)
		FileClose($hLogFile)
	EndFunc
#endregion
#region time
	Func  Sec2Time($nr_sec)
		$sec2time_hour = Int($nr_sec / 3600)
		$sec2time_min = Int(($nr_sec - $sec2time_hour * 3600) / 60)
		$sec2time_sec = $nr_sec - $sec2time_hour * 3600 - $sec2time_min * 60
		Return StringFormat('%02d:%02d:%02d', $sec2time_hour, $sec2time_min, $sec2time_sec)
	EndFunc   ;==>Sec2Time
	Func _GetUnixTime($sDate = 0);Date Format: 2013/01/01 00:00:00 ~ Year/Mo/Da Hr:Mi:Se
		Local $aSysTimeInfo = _Date_Time_GetTimeZoneInformation()
		Local $utcTime = ""
		If Not $sDate Then $sDate = _NowCalc()
		If Int(StringLeft($sDate, 4)) < 1970 Then Return ""
		If $aSysTimeInfo[0] = 2 Then
			$utcTime = _DateAdd('n', $aSysTimeInfo[1] + $aSysTimeInfo[7], $sDate)
		Else
			$utcTime = _DateAdd('n', $aSysTimeInfo[1], $sDate)
		EndIf
		Return _DateDiff('s', "1970/01/01 00:00:00", $utcTime)
	EndFunc   ;==>_GetUnixTime
#endregion

#region ====INIT ===============================================================
	Func _ConfigInitial()
;~ 		ConsoleWrite('++ConfigDBInitial() = ' & @CRLF)
		_SQLite_down()
;~ 		_DBvarInit()
		; -------check if SQLIte SubteBA db exist
		SQLite_init()
		$SQLq = "SELECT name FROM sqlite_temp_master WHERE type='table';"
		_SQLITErun($SQLq, $dbfullPath, $quietSQLQuery)
	;~ 	;-------- Init Log
	;~ 	_initLog()
		;------------------------------------------------------------------------------
	EndFunc   ;==>_ConfigDBInitial
#endregion
#region  ==== SQL functions =======================================================================
	Func SQLInsertMessage($TweetID,$TweeMsg,$TweeDate)
;~ 		ConsoleWrite('++InsertMessageSQL() = '& @crlf)
		$query='INSERT INTO messages VALUES (' & $TweetID & ',"' & $TweeMsg & '" ,' & $TweeDate & ') ;'
		if _SQLITErun($query,$dbfullPath,$quietSQLQuery) Then
			return true
		Else
			MsgBox(48+4096,"Error inserting mesages ErrNo 1010" & @CRLF & $query,0,0)
			Return false
		EndIf
	EndFunc
	Func SQLInsertUserMessage($TweetID,$TweeMsg,$UserID,$Fname,$Lname,$TweeDate)
;~ 		ConsoleWrite('++InsertMessageSQL() = '& @crlf)
		$query='INSERT INTO UserMessages VALUES (' & $TweetID & ',"' & _
		$TweeMsg & '" ,' & $UserID & ',"' & $Fname &"_"& $Lname & '",' & $TweeDate & ') ;'
		if _SQLITErun($query,$dbfullPath,$quietSQLQuery) Then
			return true
		Else
			MsgBox(48+4096,"Error inserting mesages ErrNo 1010" & @CRLF & $query,0,0)
			Return false
		EndIf
	EndFunc
	Func SQLGetUsers()
;~ 		ConsoleWrite('++SQLGetUsers() = '& @crlf)
		$query='SELECT * FROM Users ;'
		_SQLITEqry($query,$dbfullPath)
	EndFunc
	Func SQLGetActiveUsers()
;~ 		ConsoleWrite('++SQLGetActiveUsers() = '& @crlf)
		$query='SELECT * FROM Users WHERE Active=1 ;'
		_SQLITEqry($query,$dbfullPath)
	EndFunc
	Func SQLGetDevUsers()
;~ 		ConsoleWrite('++SQLGetDevUsers() = '& @crlf)
		$query='SELECT * FROM Users WHERE Active=1 AND Dev=1 ;'
		_SQLITEqry($query,$dbfullPath)
	EndFunc
	Func SQLExist_Message($TweetID)
;~ 		ConsoleWrite('++Exist_Message() = '&$TweetID& @crlf)
		$query='SELECT id FROM messages WHERE id="'&$TweetID &'";'
		_SQLITEqry($query,$dbfullPath)
		If  IsArray($qryResult) Then
			if UBound($qryResult)>1 then
				return $qryResult[1][0]
			EndIf
			return 0
		endif
		Return 0
	EndFunc
#endregion
#region  ==== send messages =======================================================================
	Func TelegramInitialMessage($UserID)
;~ 	ConsoleWrite('++TelegramInitialMessage() = '& @crlf)
		$message ="SubteBA BOT , lee los informes de Subte BA en Twitter, y los manda por este canal. "
		$message&='Este canal no es official del subte de Buenos Aires Ni de Metrovias.'  & $nuevaLinea
		$message&= $nuevaLinea
		$message&='Commandos:'  & $nuevaLinea
		$message&='/START -> Activa alertas. '  & $nuevaLinea
		$message&='/STOP  -> Desactiva alertas. '  & $nuevaLinea
		$message&='/INFO   -> Este mensaje'  & $nuevaLinea
		$message&= $nuevaLinea
		$message&='Futuros Comandos:'  & $nuevaLinea
		$message&='/ACTIVAR -> Alertas de lineas elegidas.'  & $nuevaLinea
		$message&='/DESACTIVAR -> Alertas de lineas elegidas.'  & $nuevaLinea
		$message&='/CERCANA -> Estacion mas cercana.'  & $nuevaLinea
		$message&='/ESTACIONES -> lista de estaciones por linea.'  & $nuevaLinea
		$message&='/HORARIOS -> Horarios de actividad'  & $nuevaLinea
		$message&='/MAPA -> Mapa de lineas de subte'  & $nuevaLinea
		$message&='/PROPUESTA -> Enviar propuestas'  & $nuevaLinea

		$respuesta = SendTelegramexec($UserID,$message)
		return $respuesta
	EndFunc
	Func TelegramSTOPMessage($UserID)
		$message ="Los mensajes de alertas han sido deshabilitados" & $nuevaLinea
		$message&='/START -> Para habilitar la recepcion de alertas'  & $nuevaLinea
		$message&='/INFO -> para mas informacion.'  & $nuevaLinea

		$respuesta = SendTelegramexec($UserID,$message)
		return $respuesta
	EndFunc
	Func TelegramSTARTMessage($UserID)
		$message ="Los mensajes de alertas han sido habilitados" & $nuevaLinea
		$message&='/STOP-> Para deshabilitar la recepcion de alertas'  & $nuevaLinea
		$message&='/INFO -> para mas informacion.'  & $nuevaLinea

		$respuesta = SendTelegramexec($UserID,$message)
		return $respuesta
	EndFunc
	Func TelegramErrorMessage($UserID)
		$message ="No se ha registrado el cambio requerido." & $nuevaLinea
		$message&='Reintente enviar el comando nuevamente.'  & $nuevaLinea
		$message&='INFO -> para mas informacion.'  & $nuevaLinea

		$respuesta = SendTelegramexec($UserID,$message)
		return $respuesta
	EndFunc
	Func TelegramBaseMessage($TweetID,$USRmsg,$UserID,$Fname,$Lname,$epoch)
		$message ="No logro entender el mensaje."
		$message&='Reintente enviar el comando nuevamente.'  & $nuevaLinea
		$message&='/INFO -> para mas informacion.'& $nuevaLinea & $nuevaLinea
;~ 		$message&="Su mensage:" & $nuevaLinea & $USRmsg
		$respuesta = SendTelegramexec($UserID,$message)
		SQLInsertUserMessage($TweetID,$USRmsg,$UserID,$Fname,$Lname,$epoch)
		return $respuesta
	EndFunc
	Func TelegramInformNewUser($UserID,$Fname,$Lname)
		$message ="Nunevo usuario:" & $nuevaLinea
		$message&=$Fname & "  " & $Lname
		$respuesta = SendTelegramexec($UserID,$message)
		return $respuesta
	EndFunc
	Func TelegramLocationMessage($TweetID,$USRmsg,$UserID,$Fname,$Lname,$epoch)
		$message ="La Funcion de Informacion sobre las estaciones mas cercanas "
		$message&='No esta implementado en este momento.'  & $nuevaLinea
		$message&='/INFO -> para mas informacion.'& $nuevaLinea & $nuevaLinea
;~ 		$message&="Su mensage:" & $nuevaLinea & $USRmsg
		$respuesta = SendTelegramexec($UserID,$message)
		SQLInsertUserMessage($TweetID,$USRmsg,$UserID,$Fname,$Lname,$epoch)
		return $respuesta
	EndFunc
	Func TelegramActivateMessage($TweetID,$USRmsg,$UserID,$Fname,$Lname,$epoch)
		$message ="La Funcion de Activacion de alertas por linea, "
		$message&='No esta implementado en este momento.'  & $nuevaLinea
		$message&='/INFO -> para mas informacion.'& $nuevaLinea & $nuevaLinea
;~ 		$message&=$USRmsg& $nuevaLinea
;~ 		$message&="Su mensage:" & $nuevaLinea & $USRmsg
		$respuesta = SendTelegramexec($UserID,$message)
		SQLInsertUserMessage($TweetID,$USRmsg,$UserID,$Fname,$Lname,$epoch)
		return $respuesta
	EndFunc
	Func ReformatMessage($message)
;~ 	ConsoleWrite('++ReformatMessage() = '& @crlf)
		$msgArr=StringSplit($message,"Actualizado",1)
		$diaHoraArr=stringsplit(StringStripWS($msgArr[2],1+2)," ")
		$hora=$diaHoraArr[2]
		$dia=$diaHoraArr[1]
		$msg=""&$hora&""&"     " & $dia & $nuevaLinea & StringStripWS($msgArr[1],1+2)
		return $msg
	EndFunc
	Func sendmessages($message)
		$message=ReformatMessage($message)
		SQLGetActiveUsers()
		If  IsArray($qryResult) Then
			for $i=1 to UBound($qryResult)-1
				$isDev = $qryResult[$i][4]
				$chatid = $qryResult[$i][0]
				$ChatUser = $qryResult[$i][1] & " " & $qryResult[$i][2]
				if $chatID<>"" then
					select
						Case $SendToAll = 1
							ConsoleWrite('- $chatid = ' & $chatid & "  ->  " & $ChatUser & @CRLF)
							$respuesta = SendTelegramexec($chatid,$message)
						Case $isDev = 1 AND $SendToAll = 0
							ConsoleWrite('- $chatid = ' & $chatid & "  ->  " & $ChatUser & @CRLF)
							$respuesta = SendTelegramexec($chatid,$message)
					endSelect
					;~ $respuesta  0 is ok
				endif
			next
			return true
		endif
		Return false
	EndFunc   ;==>_sendmessages
	Func SendTelegramexec($chatid,$msgtext="testeo harcoded",$DisableNotification=True)
		$urlMSG="https://api.telegram.org/" & $token & "/sendMessage?chat_id=" & $chatid & _
		"&text=" & $msgtext & "&parse_mode=HTML"
		If $DisableNotification = True Then $urlMSG &= "&disable_notification=True"
		$sGet = HttpGet($urlMSG)

		if $sget<>"0"  then
			ConsoleWrite('Tlgm sent = ' & $msgtext & @crlf )
			return 0
		Else
			$s_text="Error sending message to Telegram = " & $sGet
			ConsoleWrite('!! ' & $s_text & @crlf )
			return 1
		endif
	EndFunc
#endregion
#region  ==== Tweeter scrapping ===================================================================
	Func TweeterMessages($Username)
		ConsoleWrite('++TweeterMessages() = '& $Username &@crlf)
		$htmltxt=_ScrapTweetMessages($Username)
		if $htmltxt<>"" then
			$TweetArr = _gettweetArr($htmltxt)
			if IsArray($TweetArr) then
				$newMessagesFlag=0
				_ArraySort($TweetArr, 0, 0, 0, 2)
				For $i = 0 To UBound($TweetArr) -1
					$TweetID = $TweetArr[$i][0]
					$TweeMsg = $TweetArr[$i][1]
					$TweeDate = $TweetArr[$i][2]
					if not SQLExist_Message($TweetID) then
						SQLInsertMessage($TweetID,$TweeMsg,$TweeDate)
						$TweetMinOld= (_GetUnixTime() - $TweeDate)/60
						if $TweetMinOld < 60 then
							sendmessages($TweeMsg)
							$newMessagesFlag=1
							ConsoleWrite('+ New messages ' & _NowTime(4) & "   ")
						Else
							ConsoleWrite('+ Old messages ' & Sec2Time($TweetMinOld*60) & @crlf)
						endif
					endif
					sleep(2000)
				Next
				if $newMessagesFlag=0 then ConsoleWrite('  No new messages ' & _NowTime(4) & @CRLF)
			endif
		endif
	EndFunc
	func _ScrapTweetMessages($Username)
		Local $sData = InetRead("https://twitter.com/"&$Username)
		Local $nBytesRead = @extended
		ConsoleWrite('@@ BytesRead = ' & $nBytesRead &"   ")
		$htmltxt = BinaryToString($sData)
		If $nBytesRead < 100000 or StringInStr($htmltxt,"subteba")<1 Then
			ConsoleWrite('  Connection issue contacting  ' & "https://twitter.com/"&$Username& @crlf)
			$htmltxt=""
			Return $htmltxt
		endif
		return $htmltxt
	EndFunc
	Func _gettweetArr($htmltxt)
		$MSGArr = StringRegExp($htmltxt, '(?s)(?i)
(.*?)
', 3)
		if IsArray($MSGArr) then
			dim  $TweetMSGArr[UBound($MSGArr)]
			For $i = 0 To UBound($MSGArr) -1
				$TweetMessage = StringRegExp($MSGArr[$i], '(?s)(?i)
(.*?)
', 1)
				$mensaje = clearstring($TweetMessage[1])
				$TweetMSGArr[$i]=$mensaje
			Next
			$TweetDate = StringRegExp($htmltxt, '(?s)(?i)data-time="(.*?)"', 3)
			$TweetIDArr = StringRegExp($htmltxt, '(?s)(?i)data-tweet-id="(.*?)"', 3)
			$TweetArrAux = _mergeArray($TweetIDArr, $TweetMSGArr)
			$TweetArr = _mergeArray($TweetArrAux, $TweetDate)
			return $TweetArr
		Else
			ConsoleWrite('!!!(' &  @ScriptLineNumber & ') : Error on  $MSGArr = ' & $MSGArr & @crlf )
			return 0
		endif
	EndFunc
#endregion
#region  ==== Bot Messages handeling ===================================================================
	Func Get_BotOffSet()
;~ 		ConsoleWrite('++Get_BotOffSet() = '& @crlf)
		if NOT FileExists($OffsetFile) then
			$fileh = FileOpen($OffsetFile,1+8)
			If $fileh = -1 Then
				ConsoleWrite('   "Unable to open file 1.' & $OffsetFile )
				return 0
			endif
			FileClose($fileh)
		EndIf
		$fileh = FileOpen($OffsetFile,0)
		If $fileh = -1 Then
			ConsoleWrite('   "Unable to open file 2.' & $OffsetFile )
			return 0
		endif
		Local $offset = FileReadLine($fileh)
		if @error = -1 Then
			FileClose($fileh)
			return 0
		endif
		ConsoleWrite("Get OffSet:"& $offset)
		FileClose($fileh)
		return $offset
	EndFunc
	Func Set_BotOffSet($offset)
		ConsoleWrite('++Set_BotOffSet() = '&$offset& @crlf)
		if NOT FileExists($OffsetFile) then
			$fileh = FileOpen($OffsetFile,1+8)
			If $fileh = -1 Then
				ConsoleWrite('   "Unable to open file 3.' & $OffsetFile )
				return 0
			endif
			FileClose($fileh)
		EndIf
		$fileh = FileOpen($OffsetFile,2)
		If $fileh = -1 Then
			ConsoleWrite('   "Unable to open file 4.' & $OffsetFile )
			return 0
		endif
		FileWriteLine($fileh,$offset)
		if @error = -1 Then
			FileClose($fileh)
			return 0
		endif
		ConsoleWrite("    Set OffSet:"& $offset &@crlf)
		FileClose($fileh)
		return 1
	EndFunc
	func UpdateUsers()
		ConsoleWrite('  '&@HOUR & ':' & @MIN&  ':' & @sec & '  Update users.  ' )
		local $s=GetBotUpdates()
		if $s then
			initMsgClass()
			$s=ParseForUserUpdate($s)
;~ 			ConsoleWrite('  $s = ' & $s & @crlf )
			if $s then
				$oJSON = _OO_JSON_Init()
				$jsonObj = $oJSON.parse($s)
				if $jsonObj.ok  then
					if $jsonObj.jsonPath( "$.result").stringify() = "[[]]" then
						ConsoleWrite(' No Bot data ' & @crlf)
					Else
						ConsoleWrite('  Updating... ' & @crlf)
						$UpdateIDArr = StripIntJS($jsonObj.jsonPath( "$.result..update_id").stringify()  )
						$MSGIDArr =    StripIntJS($jsonObj.jsonPath( "$.result..message.message_id").stringify())
						$UserIDArr =   StripIntJS($jsonObj.jsonPath( "$.result..message.from.id").stringify())
						$FnameArr =    StripStrJS($jsonObj.jsonPath( "$.result..message.from.first_name").stringify())
						$LnameArr =    StripStrJS($jsonObj.jsonPath( "$.result..message.from.last_name").stringify())
						$ChatIDArr =   StripIntJS($jsonObj.jsonPath( "$.result..message.chat.id").stringify())
						$ChatFnameArr =    StripStrJS($jsonObj.jsonPath( "$.result..message.from.first_name").stringify())
						$ChatLnameArr =    StripStrJS($jsonObj.jsonPath( "$.result..message.from.last_name").stringify())
						$epochArr =    StripIntJS($jsonObj.jsonPath( "$.result..message.date").stringify())
						$menssageArr = StripStrJS($jsonObj.jsonPath( "$.result..message.text").stringify())
						$IsBot =       StripIntJS($jsonObj.jsonPath( "$.result..message.from.is_bot").stringify())

						if $UserIDArr[0] = $UpdateIDArr[0] AND  $UserIDArr[0] = $FnameArr[0] AND _
							$UserIDArr[0] = $LnameArr[0]    AND  $UserIDArr[0] = $epochArr[0] AND _
							$UserIDArr[0] = $menssageArr[0] AND  $UserIDArr[0] = $IsBot[0]  then
							$retBad=0
							for $i=1 to $UserIDArr[0]
								if $IsBot[$i] <> "true" then
									$ret=SQLregister($UserIDArr[$i],$FnameArr[$i],$LnameArr[$i],$epochArr[$i],$menssageArr[$i])
									$ret1=ParseBotMessage($UserIDArr[$i],$FnameArr[$i],$LnameArr[$i],$epochArr[$i],$menssageArr[$i],$UpdateIDArr[$i],$MSGIDArr[$i])
									ConsoleWrite('>> $ret1 = ' & $ret1 & @crlf )
									if (Not $ret) or (Not $ret1)  then	$retBad+=1
									$UpdateID=$UpdateIDArr[$i]
								Else
									ConsoleWrite('+(' & @ScriptLineNumber & ') : $menssageArr[$i] = ' & $menssageArr[$i] & @crlf )
									ConsoleWrite('+(' & @ScriptLineNumber & ') : $IsBot[$i] = ' & $IsBot[$i] & @crlf )
									if AImessage($menssageArr[$i],"callback_query") then
										if AImessage($menssageArr[$i],"CLOSE_O") then
											$ahora=1
											TelegramActivateMessage($UpdateIDArr[$i],$menssageArr[$i],$ChatIDArr[$i],$ChatFnameArr[$i],$ChatLnameArr[$i],$epochArr[$i])
											_DeleteMsg($ChatIDArr[$i], $MSGIDArr[$i])
											$KeyBoardActive=0
										else
											$ret=SQLUpdateUserAlerts($ChatIDArr[$i],$menssageArr[$i])
											if not $ret then $retBad=1
											$ahora=0.2
										endif
										$UpdateID=$UpdateIDArr[$i]
									Else
										$retBad=1
									endif
								endif
							next
							if $retBad=0 then Set_BotOffSet($UpdateID+1)
						Else
							_printFromArray($ChatIDArr,"$ChatIDArr")
							_printFromArray($ChatFnameArr,"$ChatFnameArr")
							_printFromArray($ChatLnameArr,"$ChatLnameArr")
							_printFromArray($MSGIDArr,"$MSGIDArr")
							_printFromArray($UserIDArr,"UserIDArr")
							_printFromArray($FnameArr,"FnameArr")
							_printFromArray($LnameArr,"LnameArr")
							_printFromArray($epochArr,"epochArr")
							_printFromArray($menssageArr,"menssageArr")
							_printFromArray($UpdateIDArr,"UpdateIDArr")
							_printFromArray($IsBot,"IsBot")
							ConsoleWrite('  Error in JS array . exiting..... ' & @crlf)
							exit 29
						endif
					endif
				endif
			endif
		endif
		if $KeyBoardActive=1 or $KeyboardCheckcount > 5 then
			ClearKeyBoards()
			$KeyboardCheckcount = 0
		Else
			$KeyboardCheckcount = $KeyboardCheckcount +1
		endif
		ConsoleWrite('**(' & @ScriptLineNumber & ') : $KeyBoardActive= ' & $KeyBoardActive &@crlf )
	EndFunc
	Func GetBotUpdates()
		$offset=Get_BotOffSet()
		$urlMSG="https://api.telegram.org/" & $token & "/getUpdates?offset="&$offset
		$sGet = HttpGetJson1($urlMSG)
;~ 		ConsoleWrite('@@ $sGet = ' & $sGet & @crlf )
		if $sGet<>"" then
			return $sGet
		Else
			$s_text="  Error getUpdates from Telegram = "
			ConsoleWrite('!! ' & $s_text & @crlf & "! " & $sGet)
			return false
		endif
	EndFunc
	Func StripStrJS($st)
		$st=StringReplace($st,'","',":::")
		$st=clearstring($st)
		$st=StringReplace($st,"[","")
		$st=StringReplace($st,"]","")
		$st=StringReplace($st,'"',"")
		$stArr=StringSplit($st,":::",1)
		return $stArr
	EndFunc
	Func StripIntJS($st)
		$st=StringReplace($st,',',":::")
		$st=clearstring($st)
		$st=StringReplace($st,"[","")
		$st=StringReplace($st,"]","")
		$st=StringReplace($st,'"',"")
		$stArr=StringSplit($st,":::",1)
		return $stArr
	EndFunc
	Func ParseForUserUpdate($s)
;~ 		eliminate "edited_message":{"
		$s=StringReplace($s,'"edited_message":{','"message":{')

;     check lastname
		$LNarr=StringRegExp($s,'"first_name":"(.*?)","language_code":"',1)
		if IsArray($LNarr) then
			for $r=0 to UBound($LNarr)-1
				$donde='"first_name":"[a-zA-Z]*","language_code":"'
				$pat='"first_name":"' & $LNarr[$r] & '","last_name":"xxx","language_code":"'
				$s=StringRegExpReplace($s,$donde,$pat)

				$donde='"first_name":"[a-zA-Z]*","type":"'
				$pat='"first_name":"' & $LNarr[$r] & '","last_name":"xxx","type":"'
				$s=StringRegExpReplace($s,$donde,$pat)
			next
		endif

;~ 		eliminate "callback_query":{"
		if StringInStr($s,'"callback_query":')> 0 then
			$s=StringRegExpReplace($s,'(?s)(?i)"callback_query":(.*?)"from":(.*?)},',"")
			$s=StringRegExpReplace($s,'},"chat_instance":"(.*?)"',"")
			$s=StringRegExpReplace($s,',"text":"(.*?)",',",")
			$s=StringRegExpReplace($s,',"data":"',',"text":"callback_query ')
		endif
;~ 		eliminate location info
;~ "location":{"latitude":-34.631010,"longitude":-58.469731}}
		if StringInStr($s,'"location":{')> 0 then
			$MsgClass[0]="Location"
				$posini=StringInStr($s,'{"latitude":')+12
				$posend=StringInStr($s,'"longitude":')-$posini-1
			$MsgClass[1]=StringMid($s,$posini,$posend)
				$posini=StringInStr($s,'"longitude":')+12
			$MsgClass[2]=StringMid($s,$posini,$posend)
			$s=StringRegExpReplace($s,'(?s)(?i)"location":{"latitude":(.*?),"longitude":(.*?)}' , '"text": "' & $MsgClass[0] & ":" & $MsgClass[1] & ":" & $MsgClass[2] & '"' )
		endif

;~ 		eliminate contact info
		$s=StringRegExpReplace($s,'(?s)(?i)"contact":(.*?)}'  ,  '"text": ""' )

;~ 		eliminate photo info
		$s=StringRegExpReplace($s,'(?s)(?i)"photo":\[(.*?)\]'  ,  '"text": ""' )

;~ 		replace username last-name
		$s=StringReplace($s,'"username":','"last_name":')

;~ 		eliminate sticker info
		$s=StringRegExpReplace($s,'(?s)(?i)"sticker":(.*?)}(.*?)}'  ,  '"text": ""' )
		return $s
	EndFunc
	Func SQLregister($UserID,$Fname,$Lname,$epoch,$mensage)
;~ 	ConsoleWrite('++SQLregister() = '& @crlf)
		$existUser=0
		If SQLExistUser($UserID)=$userID then $existUser=1
		if $existUser=0 then
			$setactive=1
			$ret=SQLInsertUser($UserID,$Fname,$Lname,$epoch,$setactive)
			if $ret then
				TelegramInformNewUser($DEVChatID,$Fname,$Lname)
				$ret=TelegramSTOPMessage($UserID)
				if $ret=0 then return true
			else
				$ret=TelegramErrorMessage($UserID)
				if $ret=0 then return true
			endif
			return false
		endif

		$setactive=-1
		if AIMessage($mensage,"/START") then $setactive=1
		if AIMessage($mensage,"/STOP") then $setactive=0
		if $existUser=1 AND $setactive<>-1 then
			$ret=SQLUpdateUserActive($UserID,$Fname,$Lname,$setactive)
			if $ret and $setactive=0 then
				$ret=TelegramSTOPMessage($UserID)
				if $ret=0 then return true
			endif
			if $ret and $setactive=1 then
				$ret=TelegramSTARTMessage($UserID)
				if $ret=0 then return true
			endif
			if NOT $ret then TelegramErrorMessage($UserID)
			return false
		endif

		return true
	EndFunc
	Func SQLInsertUser($UserID,$Fname,$Lname,$epoch,$active=1)
		ConsoleWrite('  Nuevo usuario = '& $Fname & "  "  & $Lname  & @crlf)
		$query='INSERT INTO Users VALUES (' & $UserID & ',"' & $Fname & '","' & $Lname & '",' & $active &',0,' & $epoch & ') ;'
		if _SQLITErun($query,$dbfullPath,$quietSQLQuery) Then
			return true
		Else
			MsgBox(48+4096,"Error inserting User ErrNo 1011" & @CRLF & $query,0,0)
			Return false
		EndIf
	EndFunc
	Func SQLUpdateUserActive($UserID,$Fname,$Lname,$active=1)
		ConsoleWrite('    Usuario Activo 1/Start 0/Stop= '&$active& "  " & $Fname & "  "  & $Lname  & @crlf)
		$query='UPDATE  Users SET Active=' & $active &' WHERE UserID='& $UserID & ' ;'
		if _SQLITErun($query,$dbfullPath,$quietSQLQuery) Then
			return true
		Else
			ConsoleWrite("       Error updating active user User ErrNo 1012" & @CRLF & $query& @crlf)
			Return false
		EndIf
	EndFunc
	Func SQLExistUser($UserID)
;~ 	ConsoleWrite('++SQLExistUser() = '& @crlf)
		$query='SELECT UserID FROM Users WHERE UserID="'&$UserID &'";'
		_SQLITEqry($query,$dbfullPath)
		If  IsArray($qryResult) Then
			if UBound($qryResult)>1 then
				return $qryResult[1][0]
			EndIf
			return 0
		endif
		Return 0
	EndFunc
	Func SQLUpdateUserAlerts($UserID,$mensage,$active=1)
		$mensage=StringReplace($mensage,"callback_query ","")
		$msgArr=StringSplit($mensage,"_")
		_printfromarray($msgArr)
		if $msgArr[2]="ON" then
			$query='UPDATE AlertasLineas SET ' & $msgArr[1] & '=1 WHERE userid=' & $UserID & ';   '
			$query&='INSERT INTO AlertasLineas (userid,' & $msgArr[1] & ')  SELECT ' & $UserID & ',1 WHERE (Select Changes() = 0);'
			if _SQLITErun($query,$dbfullPath,$quietSQLQuery) Then
				return true
			Else
				ConsoleWrite("!    Error updating alertasLineas User ErrNo 1013" & @CRLF & $query& @crlf)
				Return false
			EndIf
		endif
	EndFunc
#endregion
#region   ===================================   keyboard   ==========================
	;============== show keyboard =========================
	func KeyboardActivate($UserID)
		$keybrd =  '{"inline_keyboard":['
		$keybrd &= '['
		$keybrd &= '{"text":"Linea A","callback_data":"A_ON"},'
		$keybrd &= '{"text":"Linea B","callback_data":"B_ON"},'
		$keybrd &= '{"text":"Linea C","callback_data":"C_ON"}'
		$keybrd &= '],['
		$keybrd &= '{"text":"Linea D","callback_data":"D_ON"},'
		$keybrd &= '{"text":"Linea E","callback_data":"E_ON"},'
		$keybrd &= '{"text":"Linea H","callback_data":"H_ON"}'
		$keybrd &= '],['
		$keybrd &= '{"text":"Linea P","callback_data":"P_ON"},'
		$keybrd &= '{"text":"Linea U","callback_data":"U_ON"},'
		$keybrd &= '{"text":"Listo","callback_data":"CLOSE_ON"}'
		$keybrd &= '],['
		$keybrd &= ']'
		$keybrd &= ']}'
		$res=_SendMsg($UserID,"Sus alertas activas son:"& "" & $nuevaLinea & "Cual desea activar?","HTML",$keybrd)
		$MSGID=StringRegExp($res,'"message_id":(.*?),"from":',1)
		$UsrID=StringRegExp($res,',"chat":{"id":(.*?),"first_name":',1)
		$utime=StringRegExp($res,',"date":(.*?),"text":',1)
		if IsArray($MSGID) then	SQLregisterKeyboard($UsrID[0],$MsgID[0],$utime[0])
		if $res then return True
		return false
	EndFunc
	func KeyboardDesActivate($UserID)
		$keybrd =  '{"inline_keyboard":['
		$keybrd &= '['
		$keybrd &= '{"text":"Linea A","callback_data":"A_OFF"},'
		$keybrd &= '{"text":"Linea B","callback_data":"B_OFF"},'
		$keybrd &= '{"text":"Linea C","callback_data":"C_OFF"}'
		$keybrd &= '],['
		$keybrd &= '{"text":"Linea D","callback_data":"D_OFF"},'
		$keybrd &= '{"text":"Linea E","callback_data":"E_OFF"},'
		$keybrd &= '{"text":"Linea H","callback_data":"H_OFF"}'
		$keybrd &= '],['
		$keybrd &= '{"text":"Linea P","callback_data":"P_OFF"},'
		$keybrd &= '{"text":"Linea U","callback_data":"U_OFF"},'
		$keybrd &= '{"text":"Listo","callback_data":"CLOSE_OFF"}'
		$keybrd &= '],['
		$keybrd &= ']'
		$keybrd &= ']}'
		$res=_SendMsg($UserID,"Sus alertas activas son:"& "" & $nuevaLinea & "Cual desea desactivar?","HTML",$keybrd)
		$MSGID=StringRegExp($res,'"message_id":(.*?),"from":',1)
		$UsrID=StringRegExp($res,',"chat":{"id":(.*?),"first_name":',1)
		$utime=StringRegExp($res,',"date":(.*?),"text":',1)
		if IsArray($MSGID) then	SQLregisterKeyboard($UsrID[0],$MsgID[0],$utime[0])
		if $res then return True
		return false
	EndFunc
	Func SQLregisterKeyboard($UserID,$MsgID,$epoch)
		$query='INSERT INTO Keyboard VALUES (' & $UserID & ',' & $MsgID  & ',' & $epoch & ') ;'
		if _SQLITErun($query,$dbfullPath,$quietSQLQuery) Then
			$KeyBoardActive=1
			$ahora=0.2
			return true
		endif
		Return false
	EndFunc
	;==================   limpiar keyboard  =====================
	Func ClearKeyBoards()
		ConsoleWrite('**(' & @ScriptLineNumber & ') : ClearKeyBoards()  $KeyBoardActive= ' & $KeyBoardActive &@crlf )
		$query='SELECT UserID,MsgID FROM Keyboard WHERE Timestamp < ' & _GetUnixTime()-60 & ';'
		_SQLITEqry($query,$dbfullPath)
;~ 		$ahora=0.2
		If  IsArray($qryResult) Then
			if UBound($qryResult)>1 then
				for $i=1 to UBound($qryResult)-1
					_printFromArray($qryResult)
					ConsoleWrite('**@@(' & @ScriptLineNumber & ') : $i = ' & $i & @crlf )
					_DeleteMsg( $qryResult[$i][0],$qryResult[$i][1])
					SQLUnRegisterKeyboard($qryResult[$i][0],$qryResult[$i][1])
					$ahora=1
				next
			EndIf
		endif
	EndFunc
	Func SQLUnRegisterKeyboard($UserID,$MsgID)
		$query='DELETE FROM Keyboard WHERE UserID=' & $UserID & ' AND MsgID=' & $MsgID & ' ;'
		if _SQLITErun($query,$dbfullPath,$quietSQLQuery) Then return true
		Return false
	EndFunc
#endregion
#region   ===========================================================================
	func closeall()
		_SQLite_Close()
		_SQLite_Shutdown()
		exit 30
	EndFunc
#endregion
#region =====================================   Helpers functions  ===============================
	Func _mergeArray($array1, $array2)
		$array1 = _ArrayAdd_Column($array1)
		$size = UBound($array1)
		$newCol = UBound($array1, 2) - 1
		For $i = 0 To $size - 1
			$array1[$i][$newCol] = $array2[$i]
		Next
		Return $array1
	EndFunc   ;==>_mergeArray
	Func _ArrayAdd_Column($Array)
		Local $aTemp[UBound($Array)][UBound($Array, 0) + 1]
		For $i = 0 To UBound($Array) - 1

			For $j = 0 To UBound($Array, 0) - 1
				If UBound($Array, 0) = 1 Then $aTemp[$i][0] = $Array[$i]
				If UBound($Array, 0) > 1 Then $aTemp[$i][$j] = $Array[$i][$j]
			Next
		Next
		Return $aTemp
	EndFunc   ;==>_ArrayAdd_Column
	Func _ClearSciteConsole()
		ConsoleWrite('!!!!!!!!!!!_ClearSciteConsole Func General 92!!!!!!!!!!!!  ' & @CRLF)
		ControlSend("[CLASS:SciTEWindow]", "", "Scintilla2", "+{F5}")
	EndFunc   ;==>_ClearSciteConsole
	Func _GetDOSOutput($sCommand)
	 ConsoleWrite('++_GetDOSOutput $sCommand = ' & $sCommand & @crlf )
		Local $iPID, $sOutput = ""
		$iPID = Run('"' & @ComSpec & '" /c ' & $sCommand, "", @SW_HIDE, 2 + 4)
		While 1
			$sOutput &= StdoutRead($iPID, False, False)
			$err=@error
			If $err Then
				ConsoleWrite('!!  _GetDOSOutput $err = ' & $err & @crlf )
				ExitLoop
			EndIf
	;~ 	Sleep(10)
		WEnd
		ConsoleWrite('>> 	Output = ' & $sOutput & @crlf )
		Return $sOutput
	EndFunc   ;==>_GetDOSOutput
	Func _timeBetween($cTime, $sTime, $eTime)
		 If Not _DateIsValid('2000/01/01 ' & $cTime) Then Return -1
		 If Not _DateIsValid('2000/01/01 ' & $sTime) Then Return -2
		 If Not _DateIsValid('2000/01/01 ' & $eTime) Then Return -3
		 If _DateDiff('s', '2000/01/01 ' & $cTime & ':00', '2000/01/01 ' & $sTime & ':00') < 0 And _
			 _DateDiff('s', '2000/01/01 ' & $cTime & ':00', '2000/01/01 ' & $eTime & ':00') > 0 Then
			  Return 1
		 Else
			  Return 0
		 EndIf
	EndFunc  ; ==>_timeBetween
#endregion
#region time
	Func  Sec2Time($nr_sec)
		$sec2time_hour = Int($nr_sec / 3600)
		$sec2time_min = Int(($nr_sec - $sec2time_hour * 3600) / 60)
		$sec2time_sec = $nr_sec - $sec2time_hour * 3600 - $sec2time_min * 60
		Return StringFormat('%02d:%02d:%02d', $sec2time_hour, $sec2time_min, $sec2time_sec)
	EndFunc   ;==>Sec2Time
	Func _GetUnixTime($sDate = 0);Date Format: 2013/01/01 00:00:00 ~ Year/Mo/Da Hr:Mi:Se
		Local $aSysTimeInfo = _Date_Time_GetTimeZoneInformation()
		Local $utcTime = ""
		If Not $sDate Then $sDate = _NowCalc()
		If Int(StringLeft($sDate, 4)) < 1970 Then Return ""
		If $aSysTimeInfo[0] = 2 Then
			$utcTime = _DateAdd('n', $aSysTimeInfo[1] + $aSysTimeInfo[7], $sDate)
		Else
			$utcTime = _DateAdd('n', $aSysTimeInfo[1], $sDate)
		EndIf
		Return _DateDiff('s', "1970/01/01 00:00:00", $utcTime)
	EndFunc   ;==>_GetUnixTime
#endregion


tools/ControlAmarecTV.au3: Updated アマレコTVの録画ステータスを取得出来るようにして、start,stop時に逆動作とならないように

;
;  IkaLog
;  ======
;  Copyright (C) 2015 Takeshi HASEGAWA
;
;  Licensed under the Apache License, Version 2.0 (the 'License');
;  you may not use this file except in compliance with the License.
;  You may obtain a copy of the License at
;
;      http://www.apache.org/licenses/LICENSE-2.0
;
;  Unless required by applicable law or agreed to in writing, software
;  distributed under the License is distributed on an 'AS IS' BASIS,
;  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;  See the License for the specific language governing permissions and
;  limitations under the License.

;
;  Start and stop recording using Open Broadcaster Software(OBS).
;
;  To Start Recording:
;    ControlAmarecTV.au3 start
;
;  To Stop Recording:
;    ControlAmarecTV.au3 stop
;
;  To Reanem the recording:
;    If you want to rename the recording to a specific filename,
;    Specifcy the filename as environment variables
;    IKALOG_MP4_DESTDIR and IKALOG_MP4_DESTNAME.
;
;  Though this script will sleep seconds so that work on
;  a specific environment. The behavior is subject to change.
;

#include <FileConstants.au3>
#include <StringConstants.au3>

Func RenameFile($source)
	Local $dest = EnvGet('IKALOG_MP4_DESTNAME')
	$dest = StringReplace($dest, "/", "\")
	If $dest = '' Then
		Return False
	EndIf

	; IkaLog assumes mp4 as video file extension, but AmarecTV uses avi.
	If StringRight($dest, 4) = ".mp4" Then
		$dest = StringReplace($dest, ".mp4", ".avi", -1)
	EndIf

	FileMove($source, $dest, $FC_OVERWRITE)
EndFunc

Func FindRecentRecording()
	Local $directory = EnvGet('IKALOG_MP4_DESTDIR')

	; Replace all slashes to backslashes.
	; $directory also needs a backslash at its end.
	$directory = StringReplace($directory, "/", "\")
	If StringRight($directory, 1) <> "\" Then
		$directory = $directory & "\"
	EndIf

	Local $hSearch = FileFindFirstFile($directory & "*.avi*")

	If $hSearch = -1 Then
		MsgBox(0, "Error", "Could not find any candinates in " & $directory & " (path 1)", 10)
		Return False
	EndIf

	Local $latest_file = ''
	Local $latest_timestamp = ''

	While True
		Local $file = FileFindNextFile($hSearch)
		If @error Then ExitLoop

		Local $timestamp = FileGetTime($directory & $file, $FT_MODIFIED, $FT_STRING)
		If StringCompare($timestamp, $latest_timestamp) > 0 Then
			$latest_file = $directory & $file
			$latest_timestamp = $timestamp
		EndIf
	WEnd

	FileClose($hSearch)

	If $latest_file = '' Then
		MsgBox(0, "Error", "Could not find any candinates in " & $directory & " (path 2)", 10)
		Return False
	EndIf

	Return $latest_file
EndFunc

Func ControlAmarecTV($stop)
	Local $hWnd = WinWait('[CLASS:AmaRecTV; INSTANCE:2]', '', 1)

	If $hWnd = 0 Then
		MsgBox(0, "Error", "Could not find AmarecTV")
		Return False
	EndIf

	Local $text = ControlGetText($hWnd, "", "[CLASS:msctls_statusbar32]")
	Local $inRecording = StringInStr($text, '^撆...') > 0

	Local $click = False
	If $inRecording and $stop Then
		# Stop Recording.
		$click = True
	ElseIf (Not $inRecording) and (Not $stop) Then
		# Start Recording.
		$click = True
	EndIf

	If $click Then
		If $stop Then
			Sleep(1000 * 20)
		EndIf

		# Send Ctrl-Z

		WinActivate($hWnd)
		WinWaitActive($hWnd, "", 1)

		send("^z")

		If $stop Then
			Sleep(1000 * 10)
			Local $file  = FindRecentRecording()
			RenameFile($file)
		EndIf
	EndIf
EndFunc

$stop = StringCompare($CmdLine[1], 'stop') == 0
ControlAmarecTV($stop)

;
;  IkaLog
;  ======
;  Copyright (C) 2015 Takeshi HASEGAWA
;
;  Licensed under the Apache License, Version 2.0 (the 'License');
;  you may not use this file except in compliance with the License.
;  You may obtain a copy of the License at
;
;      http://www.apache.org/licenses/LICENSE-2.0
;
;  Unless required by applicable law or agreed to in writing, software
;  distributed under the License is distributed on an 'AS IS' BASIS,
;  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;  See the License for the specific language governing permissions and
;  limitations under the License.

;
;  Start and stop recording using Open Broadcaster Software(OBS).
;
;  To Start Recording:
;    ControlAmarecTV.au3 start
;
;  To Stop Recording:
;    ControlAmarecTV.au3 stop
;
;  To Reanem the recording:
;    If you want to rename the recording to a specific filename,
;    Specifcy the filename as environment variables
;    IKALOG_MP4_DESTDIR and IKALOG_MP4_DESTNAME.
;
;  Though this script will sleep seconds so that work on
;  a specific environment. The behavior is subject to change.
;

#include <FileConstants.au3>
#include <StringConstants.au3>

Func RenameFile($source)
	Local $dest = EnvGet('IKALOG_MP4_DESTNAME')
	$dest = StringReplace($dest, "/", "\")
	If $dest = '' Then
		Return False
	EndIf

	; IkaLog assumes mp4 as video file extension, but AmarecTV uses avi.
	If StringRight($dest, 4) = ".mp4" Then
		$dest = StringReplace($dest, ".mp4", ".avi", -1)
	EndIf

	FileMove($source, $dest, $FC_OVERWRITE)
EndFunc

Func FindRecentRecording()
	Local $directory = EnvGet('IKALOG_MP4_DESTDIR')

	; Replace all slashes to backslashes.
	; $directory also needs a backslash at its end.
	$directory = StringReplace($directory, "/", "\")
	If StringRight($directory, 1) <> "\" Then
		$directory = $directory & "\"
	EndIf

	Local $hSearch = FileFindFirstFile($directory & "*.avi*")

	If $hSearch = -1 Then
		MsgBox(0, "Error", "Could not find any candinates in " & $directory & " (path 1)", 10)
		Return False
	EndIf

	Local $latest_file = ''
	Local $latest_timestamp = ''

	While True
		Local $file = FileFindNextFile($hSearch)
		If @error Then ExitLoop

		Local $timestamp = FileGetTime($directory & $file, $FT_MODIFIED, $FT_STRING)
		If StringCompare($timestamp, $latest_timestamp) > 0 Then
			$latest_file = $directory & $file
			$latest_timestamp = $timestamp
		EndIf
	WEnd

	FileClose($hSearch)

	If $latest_file = '' Then
		MsgBox(0, "Error", "Could not find any candinates in " & $directory & " (path 2)", 10)
		Return False
	EndIf

	Return $latest_file
EndFunc

Func ControlAmarecTV($stop)
	Local $hWnd = WinWait('[CLASS:AmaRecTV]', '', 1)

	If $hWnd = 0 Then
		MsgBox(0, "Error", "Could not find AmarecTV")
		Return False
	EndIf
		WinActivate("[CLASS:AmaRecTV]")
		WinWaitActive("[CLASS:AmaRecTV]", "", 1)

	;cOȂ AutoIT A}RTV̘^Xe[^X擾łȂ
	;Local $text = StatusbarGetText($hWnd)
	;Local $text = ControlGetText($hWnd, "", "msctls_statusbar321")
	;Local $inRecording = StringCompare($text, '^撆...')
	;MsgBox(0, $hWnd, $text, 10)
	;MsgBox(0, $text, $inRecording, 10)
	;Return

	Local $click = True

	If $click Then
		If $stop Then
			Sleep(1000 * 20)
		EndIf

		# Send Ctrl-Z

		WinActivate("[CLASS:AmaRecTV]")
		WinWaitActive("[CLASS:AmaRecTV]", "", 1)

		send("^z")

		If $stop Then
			Sleep(1000 * 10)
			Local $file  = FindRecentRecording()
			RenameFile($file)
		EndIf
	EndIf
EndFunc

$stop = StringCompare($CmdLine[1], 'stop') == 0
ControlAmarecTV($stop)


Added TODO regarding the criteria of windows qualifying as a "paste target" as well as the criterion for an already-open Windows notepad (currently by [german] title)!

#include <MsgBoxConstants.au3>
#include <Date.au3>
#include <WinAPI.au3>

; Konstanten TODO bei den bestehenden (offenen) Fenstern deutlich mehr akzeptieren als nur Notepad ("Editor"), und "frisches" Notepad anders erkennen (CLASS ermitteln?)
Const $editorPath = "%SystemRoot%\system32\NOTEPAD.EXE"
Const $targetWindowClass = "[CLASS:Notepad]"

; von Funktionen als Seiteneffekt nderbare Werte
$userRequestedNewEditor = False

Func OpenNewEditor()
    $userRequestedNewEditor = True
    Run(_WinAPI_ExpandEnvironmentStrings($editorPath))
    Sleep(2000)
EndFunc

Func GetWindowList()
    Return WinList($targetWindowClass)
EndFunc

; hole oder ffne Notepad Fenster
Do
    $windowList = GetWindowList()
	If $windowlist[0][0] = 0 Then
        $hNotepad = 0
        $msgBoxResult = MsgBox(BitOR($MB_CANCELTRYCONTINUE, $MB_ICONERROR), _
		    "WatchClipBoard - Error", "No editor window found!" & @CRLF & @CRLF & _
			"  CANCEL" & Chr(9) & Chr(9) & "exit" & @CRLF & _
			"  RETRY" & Chr(9) & Chr(9) & "try again" & @CRLF & _
			"  CONTINUE" & Chr(9) & "open a new text editor window")
		Switch $msgBoxResult
          Case 11   ; Weiter
			OpenNewEditor()
			ContinueCase
		  Case 10   ; Wiederholen
		  Case Else ; Abbrechen/Dialog-Schlieen (2) etc.
            Exit 1
        EndSwitch
	Else
        If $windowlist[0][0] = 1 And ($userRequestedNewEditor Or $windowList[1][0] = "Unbenannt - Editor") Then
            $j = 1
        Else
            $allWindowTitles = ""
		    For $i = 1 To $windowlist[0][0]
		        $allWindowTitles = $allWindowTitles & $i & "  " & $windowList[$i][0] & @CRLF
		    Next
		    $inputBoxResult = InputBox("WatchClipBoard - Choice required", "These editor windows have been found:" & _
			    @CRLF & @CRLF & $allWindowTitles & @CRLF & @CRLF & "Enter the number of the editor to use," & @CRLF & _
			    "or 0 for a new editor", "0", "", -1, 250)
            If @error Then
                Exit 1
            EndIf
            $j = 1 * $inputBoxResult
        EndIf
		If $j = 0 Then
		    OpenNewEditor()
			Do
			  Sleep(300)
			  $newWindowList = GetWindowList()
			  $theNewWindowHandle = 0
			  ; alle neuen Window-Handles prfen, ob ein bisher unbekanntes dabei ist
			  For $k = 1 To $newWindowlist[0][0]
				 $knownWindow = False
				 For $i = 1 To $windowlist[0][0]
					If $windowList[$i][1] = $newWindowList[$k][1] Then
					   $knownWindow = True
					   ExitLoop
					EndIf
				 Next
				 If Not $knownWindow Then
					$theNewWindowHandle = $newWindowList[$k][1]
					ExitLoop
				 EndIf
			  Next
			Until $theNewWindowHandle <> 0
        	$hNotepad = $theNewWindowHandle
		 Else
			; prfen, ob der eingegebene Index valide ist
			If $j < 0 Or $j > $windowList[0][0] Then
			   $hNotepad = 0
			Else
			   $hNotepad = $windowList[$j][1]
			EndIf
	    EndIf
    EndIf
Until $hNotepad <> 0

; Hauptschleife
$lastClipContents = ClipGet()
While True
    $clipContents = ClipGet()
    If Not @error And $clipContents <> $lastClipContents Then
        $hCurrentWin = WinGetHandle("")
        If WinActivate($hNotepad) = 0 Then
            MsgBox($MB_ICONERROR, "WatchClipBoard - Error", "Editor window no more available!" & @CRLF & "Please restart.")
            Exit 1
        EndIf
        Sleep(300)
		If Not StringRegExp($clipContents, "^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d") Then
            Send(StringReplace(_Date_Time_SystemTimeToDateTimeStr(_Date_Time_GetLocalTime(), 1), "/", "-") & " -")
			If Not StringRegExp($clipContents, "^\s") Then
                Send(" ")
			EndIf
		EndIf
        Send("^v")
		If StringRight($clipContents, 2) <> @CRLF Then
            Send("{ENTER}")
	    EndIf
        Sleep(300)
        WinActivate($hCurrentWin)
        $lastClipContents = $clipContents
    EndIf
    Sleep(300)
WEnd

#include <MsgBoxConstants.au3>
#include <Date.au3>
#include <WinAPI.au3>

; Konstanten
Const $editorPath = "%SystemRoot%\system32\NOTEPAD.EXE"
Const $targetWindowClass = "[CLASS:Notepad]"

; von Funktionen als Seiteneffekt nderbare Werte
$userRequestedNewEditor = False

Func OpenNewEditor()
    $userRequestedNewEditor = True
    Run(_WinAPI_ExpandEnvironmentStrings($editorPath))
    Sleep(2000)
EndFunc

Func GetWindowList()
    Return WinList($targetWindowClass)
EndFunc

; hole oder ffne Notepad Fenster
Do
    $windowList = GetWindowList()
	If $windowlist[0][0] = 0 Then
        $hNotepad = 0
        $msgBoxResult = MsgBox(BitOR($MB_CANCELTRYCONTINUE, $MB_ICONERROR), _
		    "WatchClipBoard - Error", "No editor window found!" & @CRLF & @CRLF & _
			"  CANCEL" & Chr(9) & Chr(9) & "exit" & @CRLF & _
			"  RETRY" & Chr(9) & Chr(9) & "try again" & @CRLF & _
			"  CONTINUE" & Chr(9) & "open a new text editor window")
		Switch $msgBoxResult
          Case 11   ; Weiter
			OpenNewEditor()
			ContinueCase
		  Case 10   ; Wiederholen
		  Case Else ; Abbrechen/Dialog-Schlieen (2) etc.
            Exit 1
        EndSwitch
	Else
        If $windowlist[0][0] = 1 And ($userRequestedNewEditor Or $windowList[1][0] = "Unbenannt - Editor") Then
            $j = 1
        Else
            $allWindowTitles = ""
		    For $i = 1 To $windowlist[0][0]
		        $allWindowTitles = $allWindowTitles & $i & "  " & $windowList[$i][0] & @CRLF
		    Next
		    $inputBoxResult = InputBox("WatchClipBoard - Choice required", "These editor windows have been found:" & _
			    @CRLF & @CRLF & $allWindowTitles & @CRLF & @CRLF & "Enter the number of the editor to use," & @CRLF & _
			    "or 0 for a new editor", "0", "", -1, 250)
            If @error Then
                Exit 1
            EndIf
            $j = 1 * $inputBoxResult
        EndIf
		If $j = 0 Then
		    OpenNewEditor()
			Do
			  Sleep(300)
			  $newWindowList = GetWindowList()
			  $theNewWindowHandle = 0
			  ; alle neuen Window-Handles prfen, ob ein bisher unbekanntes dabei ist
			  For $k = 1 To $newWindowlist[0][0]
				 $knownWindow = False
				 For $i = 1 To $windowlist[0][0]
					If $windowList[$i][1] = $newWindowList[$k][1] Then
					   $knownWindow = True
					   ExitLoop
					EndIf
				 Next
				 If Not $knownWindow Then
					$theNewWindowHandle = $newWindowList[$k][1]
					ExitLoop
				 EndIf
			  Next
			Until $theNewWindowHandle <> 0
        	$hNotepad = $theNewWindowHandle
		 Else
			; prfen, ob der eingegebene Index valide ist
			If $j < 0 Or $j > $windowList[0][0] Then
			   $hNotepad = 0
			Else
			   $hNotepad = $windowList[$j][1]
			EndIf
	    EndIf
    EndIf
Until $hNotepad <> 0

; Hauptschleife
$lastClipContents = ClipGet()
While True
    $clipContents = ClipGet()
    If Not @error And $clipContents <> $lastClipContents Then
        $hCurrentWin = WinGetHandle("")
        If WinActivate($hNotepad) = 0 Then
            MsgBox($MB_ICONERROR, "WatchClipBoard - Error", "Editor window no more available!" & @CRLF & "Please restart.")
            Exit 1
        EndIf
        Sleep(300)
		If Not StringRegExp($clipContents, "^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d") Then
            Send(StringReplace(_Date_Time_SystemTimeToDateTimeStr(_Date_Time_GetLocalTime(), 1), "/", "-") & " -")
			If Not StringRegExp($clipContents, "^\s") Then
                Send(" ")
			EndIf
		EndIf
        Send("^v")
		If StringRight($clipContents, 2) <> @CRLF Then
            Send("{ENTER}")
	    EndIf
        Sleep(300)
        WinActivate($hCurrentWin)
        $lastClipContents = $clipContents
    EndIf
    Sleep(300)
WEnd


x Crash in GetI, deactivating it.

x Crash in GetI, deactivating it.

git-svn-id: 294f12855175db510999321cff72188496f07bec@2641 45c5ae6f-87cc-4fd0-92ee-e4f023fd80da

;Loading the DLL
$DLL=DllOpen("MediaInfo.dll")

;Info
$Info_Parameters=DllCall($DLL, "wstr", "MediaInfo_Option", "ptr", 0, "wstr", "Info_Parameters", "wstr", "")
MsgBox(0, "MediaInfo_Option - Info_Parameters", $Info_Parameters[0])
$Info_Capacities=DllCall($DLL, "wstr", "MediaInfo_Option", "ptr", 0, "wstr", "Info_Capacities", "wstr", "")
MsgBox(0, "MediaInfo_Option - Info_Capacities", $Info_Capacities[0])
$Info_Codecs=DllCall($DLL, "wstr", "MediaInfo_Option", "ptr", 0, "wstr", "Info_Codecs", "wstr", "")
MsgBox(0, "MediaInfo_Option - Info_Codecs", $Info_Codecs[0])

;New MediaInfo handle
$Handle=DllCall($DLL, "ptr", "MediaInfo_New")

;Open
$Open_Result=DllCall($DLL, "int", "MediaInfo_Open", "ptr", $Handle[0], "wstr", "Example.ogg")

;Inform with Complete=false
DllCall($DLL, "wstr", "MediaInfo_Option", "ptr", 0, "wstr", "Complete", "wstr", "")
$Inform=DllCall($DLL, "wstr", "MediaInfo_Inform", "ptr", $Handle[0], "int", 0)
MsgBox(0, "Inform with Complete=false", $Inform[0])

;Inform with Complete=true
DllCall($DLL, "wstr", "MediaInfo_Option", "ptr", 0, "wstr", "Complete", "wstr", "1")
$Inform=DllCall($DLL, "wstr", "MediaInfo_Inform", "ptr", $Handle[0], "int", 0)
MsgBox(0, "Inform with Complete=true", $Inform[0])

;Custom Inform
DllCall($DLL, "wstr", "MediaInfo_Option", "ptr", 0, "wstr", "Inform", "wstr", "General;Example : FileSize=%FileSize%")
$Inform=DllCall($DLL, "wstr", "MediaInfo_Inform", "ptr", $Handle[0], "int", 0)
MsgBox(0, "Custom Inform", $Inform[0])

;Get with Stream=General and Parameter=FileSize
$Info_Get=DllCall($DLL, "wstr", "MediaInfo_Get", "ptr", $Handle[0], "int", 0, "int", 0, "wstr", "FileSize", "int", 1, "int", 0)
MsgBox(0, "Get with Stream=General and Parameter=FileSize", $Info_Get[0])

;GetI with Stream=General and Parameter=46
;$Info_GetI=DllCall($DLL, "wstr", "MediaInfo_GetI", "ptr", $Handle[0], "int", 0, "int", 0, "int", 46, "int", 1, "int", 0)
;MsgBox(0, "Get with Stream=General and Parameter=46", $Info_GetI[0])

;Count_Get with StreamKind=Stream_Audio
$Count_Get=DllCall($DLL, "int", "MediaInfo_Count_Get", "ptr", $Handle[0], "int", 2, "int", 0)
MsgBox(0, "Count_Get with StreamKind=Stream_Audio", $Count_Get[0])

;Get with Stream=General and Parameter=AudioCount
$Info_Get=DllCall($DLL, "wstr", "MediaInfo_Get", "ptr", $Handle[0], "int", 0, "int", 0, "wstr", "AudioCount", "int", 1, "int", 0)
MsgBox(0, "Get with Stream=General and Parameter=AudioCount", $Info_Get[0])

;Get with Stream=Audio and Parameter=StreamCount
$Info_Get=DllCall($DLL, "wstr", "MediaInfo_Get", "ptr", $Handle[0], "int", 2, "int", 0, "wstr", "StreamCount", "int", 1, "int", 0)
MsgBox(0, "Get with Stream=Audio and Parameter=StreamCount", $Info_Get[0])

;Delete MediaInfo handle
$Handle=DllCall($DLL, "none", "MediaInfo_Delete", "ptr", $Handle[0])

;Close the DLL
DllClose($dll)

;Loading the DLL
$DLL=DllOpen("MediaInfo.dll")

;Info
$Info_Parameters=DllCall($DLL, "wstr", "MediaInfo_Option", "ptr", 0, "wstr", "Info_Parameters", "wstr", "")
MsgBox(0, "MediaInfo_Option - Info_Parameters", $Info_Parameters[0])
$Info_Capacities=DllCall($DLL, "wstr", "MediaInfo_Option", "ptr", 0, "wstr", "Info_Capacities", "wstr", "")
MsgBox(0, "MediaInfo_Option - Info_Capacities", $Info_Capacities[0])
$Info_Codecs=DllCall($DLL, "wstr", "MediaInfo_Option", "ptr", 0, "wstr", "Info_Codecs", "wstr", "")
MsgBox(0, "MediaInfo_Option - Info_Codecs", $Info_Codecs[0])

;New MediaInfo handle
$Handle=DllCall($DLL, "ptr", "MediaInfo_New")

;Open
$Open_Result=DllCall($DLL, "int", "MediaInfo_Open", "ptr", $Handle[0], "wstr", "Example.ogg")

;Inform with Complete=false
DllCall($DLL, "wstr", "MediaInfo_Option", "ptr", 0, "wstr", "Complete", "wstr", "")
$Inform=DllCall($DLL, "wstr", "MediaInfo_Inform", "ptr", $Handle[0], "int", 0)
MsgBox(0, "Inform with Complete=false", $Inform[0])

;Inform with Complete=true
DllCall($DLL, "wstr", "MediaInfo_Option", "ptr", 0, "wstr", "Complete", "wstr", "1")
$Inform=DllCall($DLL, "wstr", "MediaInfo_Inform", "ptr", $Handle[0], "int", 0)
MsgBox(0, "Inform with Complete=true", $Inform[0])

;Custom Inform
DllCall($DLL, "wstr", "MediaInfo_Option", "ptr", 0, "wstr", "Inform", "wstr", "General;Example : FileSize=%FileSize%")
$Inform=DllCall($DLL, "wstr", "MediaInfo_Inform", "ptr", $Handle[0], "int", 0)
MsgBox(0, "Custom Inform", $Inform[0])

;Get with Stream=General and Parameter=FileSize
$Info_Get=DllCall($DLL, "wstr", "MediaInfo_Get", "ptr", $Handle[0], "int", 0, "int", 0, "wstr", "FileSize", "int", 1, "int", 0)
MsgBox(0, "Get with Stream=General and Parameter=FileSize", $Info_Get[0])

;GetI with Stream=General and Parameter=46
$Info_GetI=DllCall($DLL, "wstr", "MediaInfo_GetI", "ptr", $Handle[0], "int", 0, "int", 0, "int", 46, "int", 1, "int", 0)
MsgBox(0, "Get with Stream=General and Parameter=46", $Info_GetI[0])

;Count_Get with StreamKind=Stream_Audio
$Count_Get=DllCall($DLL, "int", "MediaInfo_Count_Get", "ptr", $Handle[0], "int", 2, "int", 0)
MsgBox(0, "Count_Get with StreamKind=Stream_Audio", $Count_Get[0])

;Get with Stream=General and Parameter=AudioCount
$Info_Get=DllCall($DLL, "wstr", "MediaInfo_Get", "ptr", $Handle[0], "int", 0, "int", 0, "wstr", "AudioCount", "int", 1, "int", 0)
MsgBox(0, "Get with Stream=General and Parameter=AudioCount", $Info_Get[0])

;Get with Stream=Audio and Parameter=StreamCount
$Info_Get=DllCall($DLL, "wstr", "MediaInfo_Get", "ptr", $Handle[0], "int", 2, "int", 0, "wstr", "StreamCount", "int", 1, "int", 0)
MsgBox(0, "Get with Stream=Audio and Parameter=StreamCount", $Info_Get[0])

;Delete MediaInfo handle
$Handle=DllCall($DLL, "none", "MediaInfo_Delete", "ptr", $Handle[0])

;Close the DLL
DllClose($dll)


Updated deployment test script

Updated deployment test script

; ****** REMEMBER TO SWITCH OFF UAC ON TARGET MACHINE!!! *********
;
; This script will install, run and uninstall SasView
; given location of the installer. The exit code of the script
; points at failure location:
;
; 0 - OK
; 1 - Installer failure
; 2 - Problems running SasView (simple fitting)
; 3 - Uninstaller failure

#include <Constants.au3>
#include <FileConstants.au3>
#include <MsgBoxConstants.au3>
#include <WinAPIFiles.au3>

; Modifiable globals
Global $fInstallerLocation = @TempDir & "\setupSasView.exe"
if $CmdLine[0] > 0 Then
   ; If argument present - use it as local download path
   $fInstallerLocation = $CmdLine[1]
EndIf

Global $fUninstallerLocation = "C:\Program Files (x86)\SasView\unins000.exe"
Global $lTimeout = 10          ; 10 sec timeout for waiting on windows
Global $lInstallTimeout = 120  ; 2 min timeout for the installation process

; General globals
Global $installerPID = 0

;; MAIN SCRIPT
Install()
RunSasView()
Uninstall()
Exit(0)

;==============================================================

Func Install()
   ;;;;; APPLICATION INSTALLED ;;;;;;;
   Local $sSetupWindow = "Setup - SasView"
   Local $iFailFlag = 1
   ; Run setup
   if FileExists($fInstallerLocation) Then
	  $installerPID = Run($fInstallerLocation)
	  Assert($installerPID, $iFailFlag)
	  Sleep(1000)
   Else
	  ;$Error = ObjEvent(AutoIt.Error, "Setup file does not exist","123")
	  Exit($iFailFlag)
   EndIf

   ; License click through
   WinActivate($sSetupWindow)
   Local $test = WinWaitActive($sSetupWindow, "License Agreement", $lTimeout)
   ;ConsoleWrite("license agreement: " & $test)
   Assert($test, $iFailFlag)
   sleep(1000)

   Send("{TAB}{up}{ENTER}")

   ; Location
   Sleep(1000)
   $test = WinWaitActive($sSetupWindow, "Select Destination Location", $lTimeout)
   Assert($test, $iFailFlag)
   Send("{ENTER}")

   ; Icons, Startup entry
   Sleep(1000)
   $test = WinWaitActive($sSetupWindow, "Select Additional Tasks", $lTimeout)
   Assert($test, $iFailFlag)
   Send("{ENTER}")

   ; Ready to install...
   Sleep(1000)
   $test = WinWaitActive($sSetupWindow, "Ready to Install", $lTimeout)
   Assert($test, $iFailFlag)
   Send("{ENTER}")

   ; Final OK on running
   Sleep(5000)
   $test = WinWaitActive($sSetupWindow, "Completing the SasView Setup Wizard", $lInstallTimeout)
   Assert($test, $iFailFlag)
   Send("{ENTER}")
   ;ConsoleWrite("Installed" & @CRLF)

EndFunc

Func RunSasView()
   ;;;;; APPLICATION STARTED ;;;;;;;
   ; Start app - DEBUG ONLY
   ;;Run("C:\Program Files (x86)\SasView\SasView.exe")
   Local $iFailFlag = 2
   ; Wait for the window
   Sleep(1000)
   Local $hWnd = WinWaitActive("SasView  - Fitting -", "", $lTimeout)
   Assert($hWnd, $iFailFlag)

   ;;;;; Load a File
   ; Open File Load dialog
   Send("!{f}{ENTER}")
   WinWaitActive("Choose a file", "", $lTimeout)
   Assert($hWnd, $iFailFlag)
   Sleep(200)

   ; Focus is in file chooser - enter filename
   Send("C:\Program Files (x86)\SasView\test\1d_data\cyl_400_20.txt")
   Sleep(1000)
   Send("{ENTER}")

   ;; Send file to fitting
   ControlClick($hWnd, "Send To", 231)

   ;; Choose a model
   ControlCommand($hWnd, "", "ComboBox3", "SetCurrentSelection", 1)

   ;; Calculate the model
   ControlClick($hWnd, "Compute", 211)

   ;; Close SasView
   WinClose($hWnd)

   Local $hEnd = WinWaitActive("Confirm Exit", "", $lTimeout)
   Assert($hEnd, $iFailFlag)
   ControlClick($hEnd, "", "[CLASS:Button; INSTANCE:1]")

   Local $sv_closed = WinWaitClose($hWnd, "", $lTimeout)
   Assert($sv_closed, $iFailFlag)

EndFunc

Func Uninstall()
;;;;; UNINSTALL ;;;;;;;
   Local $iFailFlag = 3
   $installerPID = Run($fUninstallerLocation)
   Assert($installerPID, $iFailFlag)

   Local $sSetupWindow = "SasView Uninstall"

   Local $test = WinWaitActive($sSetupWindow, "", $lTimeout)
   Assert($test, $iFailFlag)
   Send("{TAB}{ENTER}")

   WinActivate("SasView Uninstal")
   $test = WinWaitActive($sSetupWindow, "SasView was successfully removed", $lTimeout)
   Assert($test, $iFailFlag)
   Send("{ENTER}")

EndFunc

;;; HELPER FUNCTIONS ;;;;
Func Assert($test, $lExitValue)
   ;;; Asserts $test to be non-zero and exit with code $lExitValue ;;;
   if $test == 0 Then
	  ProcessClose($installerPID)
	  Exit($lExitValue)
   EndIf
EndFunc

; ****** REMEMBER TO SWITCH OFF UAC ON TARGET MACHINE!!! *********
;
; This script will install, run and uninstall SasView
; given location of the installer. The exit code of the script
; points at failure location:
;
; 0 - OK
; 1 - Download failure
; 2 - Installer failure
; 3 - Problems running SasView (simple fitting)
; 4 - Uninstaller failure

#include <Constants.au3>
#include <FileConstants.au3>
#include <MsgBoxConstants.au3>
#include <InetConstants.au3>
#include <WinAPIFiles.au3>

; Custom error handler
;Global $oMyError = ObjEvent("AutoIt.Error","MyErrFunc")

; Modifiable globals
if $CmdLine[0] == 0 Then
   ; Expected command line with the build number as argument
   Exit (-1)
EndIf

Local $lBuildNumber = $CmdLine[1]
;Global $fInstallerLocation = "C:\util\setupSasView.exe" ; debug and testing location
Global $fInstallerLocation = @TempDir & "\setupSasView.exe"
Global $fRemoteInstallerLocation = "https://jenkins.esss.dk/sasview/job/SasView_Win7_Test/" & $lBuildNumber & "/artifact/sasview/dist/setupSasView.exe"
Global $fUninstallerLocation = "C:\Program Files (x86)\SasView\unins000.exe"
Global $lTimeout = 10          ; 10 sec timeout for waiting on windows
Global $lInstallTimeout = 120  ; 2 min timeout for the installation process

; General globals
Global $installerPID = 0

;; MAIN SCRIPT
Download()
Install()
RunSasView()
Uninstall()

Exit(0)

;==============================================================
Func Download()
   ; Download the file in the background with the selected option of 'force a reload from the remote site.'
   ConsoleWrite("Downloading...." & @CRLF)
   Local $iFailFlag = 1
   Local $hDownload = InetGet($fRemoteInstallerLocation, $fInstallerLocation, $INET_FORCERELOAD)

    ; Close the handle returned by InetGet.
    InetClose($hDownload)
	Assert($hDownload, $iFailFlag)
	ConsoleWrite("Installer downloaded successfully to " & $fInstallerLocation & @CRLF)

EndFunc

Func Install()
   ;;;;; APPLICATION INSTALLED ;;;;;;;
   Local $sSetupWindow = "Setup - SasView"
   Local $iFailFlag = 2
   ; Run setup
   if FileExists($fInstallerLocation) Then
	  $installerPID = Run($fInstallerLocation)
	  Assert($installerPID, $iFailFlag)
	  Sleep(1000)
   Else
	  ;$Error = ObjEvent(AutoIt.Error, "Setup file does not exist","123")
	  Exit($iFailFlag)
   EndIf

   ; License click through
   WinActivate($sSetupWindow) ; <-- REQUIRED when connecting from another host
   Local $test = WinWaitActive($sSetupWindow, "License Agreement", $lTimeout)
   ;ConsoleWrite("license agreement: " & $test)
   Assert($test, $iFailFlag)
   sleep(1000)

   Send("{TAB}{up}{ENTER}")

   ; Location
   Sleep(1000)
   $test = WinWaitActive($sSetupWindow, "Select Destination Location", $lTimeout)
   Assert($test, $iFailFlag)
   Send("{ENTER}")

   ; Icons, Startup entry
   Sleep(1000)
   $test = WinWaitActive($sSetupWindow, "Select Additional Tasks", $lTimeout)
   Assert($test, $iFailFlag)
   Send("{ENTER}")

   ; Ready to install...
   Sleep(1000)
   $test = WinWaitActive($sSetupWindow, "Ready to Install", $lTimeout)
   Assert($test, $iFailFlag)
   Send("{ENTER}")

   ; Final OK on running
   Sleep(5000)
   $test = WinWaitActive($sSetupWindow, "Completing the SasView Setup Wizard", $lInstallTimeout)
   Assert($test, $iFailFlag)
   Send("{ENTER}")
   ;ConsoleWrite("Installed" & @CRLF)

EndFunc

Func RunSasView()
   ;;;;; APPLICATION STARTED ;;;;;;;
   ; Start app - DEBUG ONLY
   ;;Run("C:\Program Files (x86)\SasView\SasView.exe")
   Local $iFailFlag = 2
   ; Wait for the window
   Sleep(1000)
   Local $hWnd = WinWaitActive("SasView  - Fitting -", "", $lTimeout)
   Assert($hWnd, $iFailFlag)

   ;;;;; Load a File
   ; Open File Load dialog
   Send("!{f}{ENTER}")
   WinWaitActive("Choose a file", "", $lTimeout)
   Assert($hWnd, $iFailFlag)
   Sleep(200)

   ; Focus is in file chooser - enter filename
   Send("C:\Program Files (x86)\SasView\test\1d_data\cyl_400_20.txt")
   Sleep(1000)
   Send("{ENTER}")

   ;; Send file to fitting
   ControlClick($hWnd, "Send To", 231)

   ;; Choose a model
   ControlCommand($hWnd, "", "ComboBox3", "SetCurrentSelection", 1)

   ;; Calculate the model
   ControlClick($hWnd, "Compute", 211)

   ;; Close SasView
   WinClose($hWnd)

   Local $hEnd = WinWaitActive("Confirm Exit", "", $lTimeout)
   Assert($hEnd, $iFailFlag)
   ControlClick($hEnd, "", "[CLASS:Button; INSTANCE:1]")

   Local $sv_closed = WinWaitClose($hWnd, "", $lTimeout)
   Assert($sv_closed, $iFailFlag)

EndFunc

Func Uninstall()
;;;;; UNINSTALL ;;;;;;;
   Local $iFailFlag = 3
   $installerPID = Run($fUninstallerLocation)
   Assert($installerPID, $iFailFlag)

   Local $sSetupWindow = "SasView Uninstall"

   Local $test = WinWaitActive($sSetupWindow, "", $lTimeout)
   Assert($test, $iFailFlag)
   Send("{TAB}{ENTER}")

   WinActivate("SasView Uninstal")
   $test = WinWaitActive($sSetupWindow, "SasView was successfully removed", $lTimeout)
   Assert($test, $iFailFlag)
   Send("{ENTER}")

EndFunc

;;; HELPER FUNCTIONS ;;;;
Func Assert($test, $lExitValue)
   ;;; Asserts $test to be non-zero and exit with code $lExitValue ;;;
   if $test == 0 Then
	  ProcessClose($installerPID)
	  Exit($lExitValue)
   EndIf
EndFunc


catch error on StringReverse function missing

#include <String.au3>
#include <File.au3>
#include <Array.au3>

Global $string, $password, $email, $data, $path, $search, $file, $root
$root = "HKEY_CLASSES_ROOT\muledump"

Func _write()
	RegWrite($root,"","REG_SZ","URL: muledump Protocol")
	RegWrite($root,"URL Protocol","REG_SZ","")
	RegWrite($root & "\shell")
	RegWrite($root & "\shell\open")
	RegWrite($root & "\shell\open\command","","REG_SZ", @AutoItExe & ' "' & @ScriptFullPath & '" %1')
	If RegRead("HKEY_CLASSES_ROOT\muledump","") Then
		MsgBox(64,"mulelogin","muledump: URL handler installed")
	Else
		MsgBox(16,"mulelogin","Unable to write to registry" & @CRLF & "Try again with admin rights")
	EndIf
	Exit
EndFunc

Func _install()
	Local $k
	$k = RegEnumKey($root, 1)
	If @error == 2 Then
		MsgBox(16,"mulelogin","Unable to open the registry" & @CRLF & "Try again with admin rights")
		Exit
	EndIf
	If @error == 1 Then _write()
	$k = MsgBox(6 + 32, 'mulelogin', _
		'URL handler is already installed. Uninstall?' & @CRLF & @CRLF & _
		'"Cancel" to do nothing' & @CRLF & _
		'"Try Again" to reinstall' & @CRLF & _
		'"Continue" to uninstall')
	If $k == 10 Then _write()
	If $k == 11 Then
		RegDelete($root)
		if @error <> 0 Then
			MsgBox(16,"mulelogin","Unable to delete the key" & @CRLF & "Try again with admin rights")
		Else
			MsgBox(64,"mulelogin","muledump: URL handler uninstalled")
		EndIf
	EndIf
	Exit
EndFunc

Func _length($string)
	Local $binlength, $declength, $array, $result
	$declength = StringLen($string)/2
    While $declength > 0
        $binlength &= Mod($declength,2)
        $declength = Floor($declength/2)
    WEnd
	$binlength = StringReverse($binlength)
	if @error <> 0 Then
		$binlength = _StringReverse($binlength)
	EndIf
	$binlength = $binlength & "1"
	$array = StringSplit($binlength,"")
	For $i = 1 To $array[0]
        $array[0] -= 1
        If $array[$i] = "1" Then $result += 2 ^ ($array[0])
	Next
	Return Hex(Int($result),2)
EndFunc

Func _build()
	;header
	$string  = "0x 00 BF" 						;Magic Number		 2 bytes
	$string &= "?? ?? ?? ??"					;Size				 4 bytes
	$string &= "54 43 53 4F 00 04 00 00 00 00"	;Marker				10 bytes
	$string &= "00 05"							;Name Size			 2 bytes
	$string &= "52 6F 74 4D 47"					;"RotMG"			 5 bytes
	$string &= "00 00 00"						;Padding			 3 bytes
	$string &= "03"								;AMF Version		 1 byte

	;data
	$string &= "11"								;Length				 1 byte
	$string &= "50 61 73 73 77 6F 72 64"		;"Password"			 8 bytes
	$string &= "06"								;Type (string) 		 1 byte
	$string &= _length($password)				;Length				 1 byte
	$string &= $password						;Actual Password	 ? bytes
	$string &= "00"								;AMF Padding		 1 byte

	$string &= "09"								;Length				 1 byte
	$string &= "47 55 49 44"					;"GUID"				 4 bytes
	$string &= "06"								;Type (string)		 1 byte
	$string &= _length($email)					;Length				 1 byte
	$string &=  $email							;Email				 ? bytes
	$string &= "00"								;AMF Padding		 1 byte

	$string = StringReplace($string," ","")
	$string = StringRegExpReplace($string,"\?{8}",Hex(Int(StringLen(StringMid($string,15))/2)))
EndFunc

If $CmdLine[0] = 0 Then _install()

$data = StringReplace($CmdLine[1],"muledump:","")
$data = StringSplit($data,"-")
$email = $data[1]
$password = $data[2]

_build()

$path = @AppDataDir & "\Macromedia\Flash Player\#SharedObjects\"
$search = FileFindFirstFile($path & "*")
$path &= FileFindNextFile($search) & "\www.realmofthemadgod.com\RotMG.sol"
FileClose($search)
$file = FileOpen($path,18)
FileWrite($file,$string)
FileClose($file)

ShellExecute("http://www.realmofthemadgod.com/")
; replace the line above if you're using a projector
; for example, with totalcmd + swfview
;ShellExecute('C:\Program Files\Total Commander\Totalcmd.exe', '/S=L:Pswfview e:\temp\rotmg\loader.swf')

#include <String.au3>
#include <File.au3>
#include <Array.au3>

Global $string, $password, $email, $data, $path, $search, $file, $root
$root = "HKEY_CLASSES_ROOT\muledump"

Func _write()
	RegWrite($root,"","REG_SZ","URL: muledump Protocol")
	RegWrite($root,"URL Protocol","REG_SZ","")
	RegWrite($root & "\shell")
	RegWrite($root & "\shell\open")
	RegWrite($root & "\shell\open\command","","REG_SZ", @AutoItExe & ' "' & @ScriptFullPath & '" %1')
	If RegRead("HKEY_CLASSES_ROOT\muledump","") Then
		MsgBox(64,"mulelogin","muledump: URL handler installed")
	Else
		MsgBox(16,"mulelogin","Unable to write to registry" & @CRLF & "Try again with admin rights")
	EndIf
	Exit
EndFunc

Func _install()
	Local $k
	$k = RegEnumKey($root, 1)
	If @error == 2 Then
		MsgBox(16,"mulelogin","Unable to open the registry" & @CRLF & "Try again with admin rights")
		Exit
	EndIf
	If @error == 1 Then _write()
	$k = MsgBox(6 + 32, 'mulelogin', _
		'URL handler is already installed. Uninstall?' & @CRLF & @CRLF & _
		'"Cancel" to do nothing' & @CRLF & _
		'"Try Again" to reinstall' & @CRLF & _
		'"Continue" to uninstall')
	If $k == 10 Then _write()
	If $k == 11 Then
		RegDelete($root)
		if @error <> 0 Then
			MsgBox(16,"mulelogin","Unable to delete the key" & @CRLF & "Try again with admin rights")
		Else
			MsgBox(64,"mulelogin","muledump: URL handler uninstalled")
		EndIf
	EndIf
	Exit
EndFunc

Func _length($string)
	Local $binlength, $declength, $array, $result
	$declength = StringLen($string)/2
    While $declength > 0
        $binlength &= Mod($declength,2)
        $declength = Floor($declength/2)
    WEnd
	$binlength = StringReverse($binlength)
	$binlength = $binlength & "1"
	$array = StringSplit($binlength,"")
	For $i = 1 To $array[0]
        $array[0] -= 1
        If $array[$i] = "1" Then $result += 2 ^ ($array[0])
	Next
	Return Hex(Int($result),2)
EndFunc

Func _build()
	;header
	$string  = "0x 00 BF" 						;Magic Number		 2 bytes
	$string &= "?? ?? ?? ??"					;Size				 4 bytes
	$string &= "54 43 53 4F 00 04 00 00 00 00"	;Marker				10 bytes
	$string &= "00 05"							;Name Size			 2 bytes
	$string &= "52 6F 74 4D 47"					;"RotMG"			 5 bytes
	$string &= "00 00 00"						;Padding			 3 bytes
	$string &= "03"								;AMF Version		 1 byte

	;data
	$string &= "11"								;Length				 1 byte
	$string &= "50 61 73 73 77 6F 72 64"		;"Password"			 8 bytes
	$string &= "06"								;Type (string) 		 1 byte
	$string &= _length($password)				;Length				 1 byte
	$string &= $password						;Actual Password	 ? bytes
	$string &= "00"								;AMF Padding		 1 byte

	$string &= "09"								;Length				 1 byte
	$string &= "47 55 49 44"					;"GUID"				 4 bytes
	$string &= "06"								;Type (string)		 1 byte
	$string &= _length($email)					;Length				 1 byte
	$string &=  $email							;Email				 ? bytes
	$string &= "00"								;AMF Padding		 1 byte

	$string = StringReplace($string," ","")
	$string = StringRegExpReplace($string,"\?{8}",Hex(Int(StringLen(StringMid($string,15))/2)))
EndFunc

If $CmdLine[0] = 0 Then _install()

$data = StringReplace($CmdLine[1],"muledump:","")
$data = StringSplit($data,"-")
$email = $data[1]
$password = $data[2]

_build()

$path = @AppDataDir & "\Macromedia\Flash Player\#SharedObjects\"
$search = FileFindFirstFile($path & "*")
$path &= FileFindNextFile($search) & "\www.realmofthemadgod.com\RotMG.sol"
FileClose($search)
$file = FileOpen($path,18)
FileWrite($file,$string)
FileClose($file)

ShellExecute("http://www.realmofthemadgod.com/")
; replace the line above if you're using a projector
; for example, with totalcmd + swfview
;ShellExecute('C:\Program Files\Total Commander\Totalcmd.exe', '/S=L:Pswfview e:\temp\rotmg\loader.swf')


assertEquals simple

assertEquals simple

Func _test_($testName)
	$oClassObject = _AutoItObject_Class()
	$oClassObject.Create()
    $dicSteps = ObjCreate("Scripting.Dictionary")

	With $oClassObject
		.AddMethod("addStep","addStep")
		.AddMethod("countSteps","countSteps")
		.AddMethod("assertTrue","assertTrue")
		.AddMethod("assertFalse","assertFalse")
		.AddMethod("assertEquals","assertEquals")
        .AddMethod("stepPassed","stepPassed")
        .AddMethod("stepFailed","stepFailed")
        .AddMethod("duration","duration")
	EndWith

	With $oClassObject
		.AddProperty("_type_", $ELSCOPE_PUBLIC, "_test_") ;Object type
		.AddProperty("name", $ELSCOPE_PUBLIC,$testName)
		.AddProperty("steps", $ELSCOPE_PUBLIC, $dicSteps) ;Dictionary with test case steps
		.AddProperty("stepCount",$ELSCOPE_PRIVATE,0)
		.AddProperty("pass",$ELSCOPE_PUBLIC,True)
        .AddProperty("testResult",$ELSCOPE_PUBLIC,"Passed") ;0 Failed - 1 OK
		.AddProperty("testStepsFailed",$ELSCOPE_PUBLIC,0)
		.AddProperty("testStepsPassed",$ELSCOPE_PUBLIC,0)
        .AddProperty("beginTime",$ELSCOPE_PRIVATE,_NowCalc())
        .AddProperty("endTime",$ELSCOPE_PRIVATE,_NowCalc())
	EndWith

	Return $oClassObject.Object
EndFunc

Func assertTrue($this, $assertText, $assertion)
	$this.addStep($assertText, $assertion)
    $this.endTime = _NowCalc()
    Return $assertion
EndFunc

Func assertFalse($this, $assertText, $falseAssertion)
    Return $this.assertTrue($assertText,Not $falseAssertion)
EndFunc

Func assertEquals($this, $assertText, $first, $second)
    Return $this.assertTrue($assertText,$first = $second)
EndFunc

Func addStep($this,$stepText,$assertion)
	Local $step[2] = [$stepText,$assertion]
    $this.stepCount = $this.stepCount + 1
    $this.steps.Add($this.stepCount, $step)

    If $assertion Then
        $this.stepPassed()
    Else
        $this.stepFailed()
	EndIf
EndFunc

Func stepFailed($this)
    $this.pass = False
    $this.testResult = "Failed"
	$this.testStepFailed = $this.testStepFailed + 1
EndFunc

Func stepPassed($this)
    $this.testStepPassed = $this.testStepPassed + 1
EndFunc

Func duration($this)
    Return $this.endTime - $this.beginTime
EndFunc

Func _test_($testName)
	$oClassObject = _AutoItObject_Class()
	$oClassObject.Create()
    $dicSteps = ObjCreate("Scripting.Dictionary")

	With $oClassObject
		.AddMethod("addStep","addStep")
		.AddMethod("countSteps","countSteps")
		.AddMethod("assertTrue","assertTrue")
		.AddMethod("assertFalse","assertFalse")
		.AddMethod("assertEquals","assertEquals")
        .AddMethod("stepPassed","stepPassed")
        .AddMethod("stepFailed","stepFailed")
        .AddMethod("duration","duration")
	EndWith

	With $oClassObject
		.AddProperty("_type_", $ELSCOPE_PUBLIC, "_test_") ;Object type
		.AddProperty("name", $ELSCOPE_PUBLIC,$testName)
		.AddProperty("steps", $ELSCOPE_PUBLIC, $dicSteps) ;Dictionary with test case steps
		.AddProperty("stepCount",$ELSCOPE_PRIVATE,0)
		.AddProperty("pass",$ELSCOPE_PUBLIC,True)
        .AddProperty("testResult",$ELSCOPE_PUBLIC,"Passed") ;0 Failed - 1 OK
		.AddProperty("testStepsFailed",$ELSCOPE_PUBLIC,0)
		.AddProperty("testStepsPassed",$ELSCOPE_PUBLIC,0)
        .AddProperty("beginTime",$ELSCOPE_PRIVATE,_NowCalc())
        .AddProperty("endTime",$ELSCOPE_PRIVATE,_NowCalc())
	EndWith

	Return $oClassObject.Object
EndFunc

Func assertTrue($this, $assertText, $assertion)
	$this.addStep($assertText, $assertion)
    $this.endTime = _NowCalc()
    Return $assertion
EndFunc

Func assertFalse($this, $assertText, $falseAssertion)
    Return $this.assertTrue($assertText,Not $falseAssertion)
EndFunc

Func assertEquals($this, $assertText, $first, $second)
    ConsoleWrite($first = $second)
    Return $this.assertTrue($assertText,$first = $second)
EndFunc

Func addStep($this,$stepText,$assertion)
	Local $step[2] = [$stepText,$assertion]
    $this.stepCount = $this.stepCount + 1
    $this.steps.Add($this.stepCount, $step)

    If $assertion Then
        $this.stepPassed()
    Else
        $this.stepFailed()
	EndIf
EndFunc

Func stepFailed($this)
    $this.pass = False
    $this.testResult = "Failed"
	$this.testStepFailed = $this.testStepFailed + 1
EndFunc

Func stepPassed($this)
    $this.testStepPassed = $this.testStepPassed + 1
EndFunc

Func duration($this)
    Return $this.endTime - $this.beginTime
EndFunc