parse location messages

parse location messages

#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 la recepcion de alertas. '  & $nuevaLinea
		$message&='/STOP  -> Desactiva la recepcion de alertas. '  & $nuevaLinea
		$message&='/INFO -> Muestra este mensage'  & $nuevaLinea
		$message&= $nuevaLinea
		$message&='Futuros Comandos:'  & $nuevaLinea
		$message&='/ACTIVAR A B -> Recepcion de alertas de la Linea A, B (C, D, E, H, P, U)'  & $nuevaLinea
		$message&='/DESACTIVAR A B -> Recepcion de alertas de la Linea A, B (C, D, E, H, P, U)'  & $nuevaLinea
		$message&='/ESTACIONES A -> lista de estaciones de la linea A( B, C, D, E, H, P, U)'  & $nuevaLinea
		$message&='/HORARIOS  -> Horarios de actividad'  & $nuevaLinea
		$message&='/MAPA  -> Mapa de lineas de subte'  & $nuevaLinea
		$message&='/PROPUESTA 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
			$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()  )
						$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())
						$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])
									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 )
									$retBad=1
								endif
							next
							if $retBad=0 then Set_BotOffSet($UpdateID+1)
						Else
							_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
	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":{')

;~ 		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": ""' )

;~ 		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
#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

#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 la recepcion de alertas. '  & $nuevaLinea
		$message&='/STOP  -> Desactiva la recepcion de alertas. '  & $nuevaLinea
		$message&='/INFO -> Muestra este mensage'  & $nuevaLinea
		$message&= $nuevaLinea
		$message&='Futuros Comandos:'  & $nuevaLinea
		$message&='/ACTIVAR A B -> Recepcion de alertas de la Linea A, B (C, D, E, H, P, U)'  & $nuevaLinea
		$message&='/DESACTIVAR A B -> Recepcion de alertas de la Linea A, B (C, D, E, H, P, U)'  & $nuevaLinea
		$message&='/ESTACIONES A -> lista de estaciones de la linea A( B, C, D, E, H, P, U)'  & $nuevaLinea
		$message&='/HORARIOS  -> Horarios de actividad'  & $nuevaLinea
		$message&='/MAPA  -> Mapa de lineas de subte'  & $nuevaLinea
		$message&='/PROPUESTA 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 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
			$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()  )
						$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())
						$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])
									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 )
									$retBad=1
								endif
							next
							if $retBad=0 then Set_BotOffSet($UpdateID+1)
						Else
							_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
	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 location info
;~ "location":{"latitude":-34.631010,"longitude":-58.469731}}
		$s=StringRegExpReplace($s,'(?s)(?i)"location":{"latitude":(.*?),"longitude":(.*?)}'  ,  '"text": ""' )
;~ 		eliminate contact info
		$s=StringRegExpReplace($s,'(?s)(?i)"contact":(.*?)}'  ,  '"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
#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


cleanup

cleanup

Global $stream_dll_hand

Func StreamWinEventLogs($output_dir = "c:\temp\")
	 ; Start streaming logs
	 ConsoleWrite("StreamLogs" & @CRLF)

	$stream_dll_hand = DllOpen("event-stream.dll")
	ConsoleWrite("dll handle  " & $stream_dll_hand  & @CRLF)
	if $stream_dll_hand < 0 Then
		ConsoleWrite("Error opening dll " & $stream_dll_hand  & @CRLF)
		return $stream_dll_hand
	EndIf

	Local $ret = DllCall ( $stream_dll_hand, "int:cdecl", "StartStreamEventsThread", "WSTR", "Microsoft-Windows-Sysmon/Operational", "WSTR", $output_dir & "Microsoft-Windows-SysmonOperational.xml")
	if $ret Then
		ConsoleWrite("error sysmon " & $ret  & @CRLF)
		return $ret
	Endif

	$ret = DllCall ( $stream_dll_hand, "int:cdecl", "StartStreamEventsThread", "WSTR", "System", "WSTR",  $output_dir &  "System.xml")
	if $ret Then
		ConsoleWrite("error System " & $ret  & @CRLF)
		return $ret
	Endif

	$ret = DllCall ( $stream_dll_hand, "int:cdecl", "StartStreamEventsThread", "WSTR", "Application", "WSTR",  $output_dir &  "Application.xml")
	if $ret Then
		ConsoleWrite("error Application " & $ret  & @CRLF)
		return $ret
	Endif

	    $ret = DllCall ( $stream_dll_hand, "int:cdecl", "StartStreamEventsThread", "WSTR", "Security", "WSTR",  $output_dir &  "Security.xml")
	if $ret Then
		ConsoleWrite("error Application " & $ret  & @CRLF)
		return $ret
	Endif

	$ret = DllCall ( $stream_dll_hand, "int:cdecl", "StartStreamEventsThread", "WSTR", "Windows Powershell", "WSTR",  $output_dir &  "Microsoft-Windows-PowershellOperational.xml")
	if $ret Then
		ConsoleWrite("error powershell " & $ret  & @CRLF)
		return $ret
	Endif

	return 0
EndFunc

Func StopStreamWinEventLogs()
	DllClose($stream_dll_hand)
EndFunc

Global $stream_dll_hand

Func StreamWinEventLogs($output_dir = "c:\temp\")
	 ; Start streaming logs
	 ConsoleWrite("StreamLogs" & @CRLF)

	$stream_dll_hand = DllOpen("event-stream.dll")
	ConsoleWrite("dll handle  " & $stream_dll_hand  & @CRLF)
	if $stream_dll_hand < 0 Then
		ConsoleWrite("Error opening dll " & $stream_dll_hand  & @CRLF)
		return $stream_dll_hand
	EndIf

	Local $ret = DllCall ( $stream_dll_hand, "int:cdecl", "StartStreamEventsThread", "WSTR", "Microsoft-Windows-Sysmon/Operational", "WSTR", $output_dir & "Microsoft-Windows-SysmonOperational.xml")
	if $ret Then
		ConsoleWrite("error sysmon " & $ret  & @CRLF)
		return $ret
	Endif

	$ret = DllCall ( $stream_dll_hand, "int:cdecl", "StartStreamEventsThread", "WSTR", "System", "WSTR",  $output_dir &  "System.xml")
	if $ret Then
		ConsoleWrite("error System " & $ret  & @CRLF)
		return $ret
	Endif

	$ret = DllCall ( $stream_dll_hand, "int:cdecl", "StartStreamEventsThread", "WSTR", "Application", "WSTR",  $output_dir &  "Application.xml")
	if $ret Then
		ConsoleWrite("error Application " & $ret  & @CRLF)
		return $ret
	Endif

	    $ret = DllCall ( $stream_dll_hand, "int:cdecl", "StartStreamEventsThread", "WSTR", "Security", "WSTR",  $output_dir &  "Security.xml")
	if $ret Then
		ConsoleWrite("error Application " & $ret  & @CRLF)
		return $ret
	Endif

	$ret = DllCall ( $stream_dll_hand, "int:cdecl", "StartStreamEventsThread", "WSTR", "Windows Powershell", "WSTR",  $output_dir &  "Microsoft-Windows-PowershellOperational.xml")
	if $ret Then
		ConsoleWrite("error powershell " & $ret  & @CRLF)
		return $ret
	Endif

	ConsoleWrite("dll ret " & $ret  & @CRLF)
	$ret = DllCall ( $stream_dll_hand, "int:cdecl", "HelloWorld0")
	ConsoleWrite("dll ret " & $ret  & @CRLF)
	$ret = DllCall ( $stream_dll_hand, 'int:cdecl', "HelloWorld1", "int", 0)

	ConsoleWrite("dll ret " & $ret  & @CRLF)
	return 0
EndFunc

Func StopStreamWinEventLogs()
	DllClose($stream_dll_hand)
EndFunc


Updated to 2.0 version (can't test since i'm using mac now and there's no 2.0 instalers either. Also converted some tabs to spaces etc.

;;  Copyright 2008 Nokia Siemens Networks Oyj
;;
;;  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.

;; Robot Framework One Click Installer for Windows
;;
;; This installer installs Robot Framework and its preconditions Python and
;; Jython (optional). If installer is executed without arguments, it opens a
;; dialog explaining the options and asking the user to enter the installation
;; directory. If a command line options is given, it must be a path to an
;; existing directory and it is used as installation directory.
;;
;; For more information about this script see $USAGE below. To learn more
;; about silent Python installation, see url [1]. Silent Jython installation
;; options can be seen with command [2].
;;
;; [1] http://www.python.org/download/releases/2.5/msi/#automated
;; [2] java -jar jython_installer-2.2.x.jar --help

;;
;; Config
;;

; Expected patterns for installer names and target directory names.
$PYTHON_DIR_NAME = "Python25"
$JYTHON_DIR_NAME = "Jython22"
$PYTHON_PATTERN = "python-2.5*.msi"
$ROBOT_PATTERN = "robotframework-2.*.exe"
$JYTHON_PATTERN = "jython_installer-2.2*.jar"

; Usage to show to the user. If major versions of installed software are changed update them also here!!
; Patterns and directory names above are used in the usage so that they don't need to be updated.
$USAGE = "One Click Installer installs Robot Framework and its preconditions Python and Jython (optional). " & _
         "It also sets Robot Framework start-up scripts (pybot, jybot, rebot) as well as Python and Jython executables " & _
         "into %PATH% environment variable so that they can be executed from the command line. (Note that " & _
         "you need to restart the command prompt for these changes to take effect.)" & @CRLF & @CRLF & _
         "You should use this installer ONLY if you don't previously have Python or Jython installed. " & _
         "In that case, and also if you want to have a custom installation, you need to install needed " & _
         "components separately." & @CRLF & @CRLF & _
         "One Click Installer requires that you have all the required component installers in the same directory " & _
         "with it and that they have expected names. If Robot Framework or Python installer is missing, " & _
         "installation fails. If Jython installer doesn't exist, Jython is simply not installed. Note that " & _
         "in order to install Jython, Java 1.4 or newer must be already installed. Supported " & _
         "versions are Robot Framework 2.x, Python 2.5.x and Jython 2.2.x where '.x' means that any minor version " & _
         "(e.g. 2.5 or 2.5.2) is OK. These installers can be downloaded from respective project websites if " & _
         "they are missing. Expected patterns for installer names are '" & $ROBOT_PATTERN & "', '" & _
         $PYTHON_PATTERN & "' and '" & $JYTHON_PATTERN & "'." & @CRLF & @CRLF & _
         "The only thing you need to specify is the base directory where to install Python and Jython. " & _
         "They are installed into directories '" & $PYTHON_DIR_NAME & "' and '" & $JYTHON_DIR_NAME & "', " & _
         "respectively, inside the given base directory. Robot Framework itself is installed under Python " & _
         "installation directory and its startup scripts can be found from '[PYTHON]\Scripts' and code from " & _
         "'[PYTHON]\Lib\site-packages'." & @CRLF & @CRLF & _
         "Note that the specified base directory MUST exist and Python and Jython directories inside it must not. " & _
         "It is also not recommended to use a path containing spaces. Good candidates include directories like " & _
         "'C:\' and 'C:\APPS'."

;;
;; Main
;;

$base_dir = GetBaseDirectory()
$python_installer = GetRequiredInstaller($PYTHON_PATTERN, "Python")
$robot_installer = GetRequiredInstaller($ROBOT_PATTERN, "Robot")
$jython_installer = GetOptionalInstaller($JYTHON_PATTERN)
$python_dir = GetPythonDir($base_dir & $PYTHON_DIR_NAME)
$jython_dir = GetJythonDir($base_dir & $PYTHON_DIR_NAME, $jython_installer)
InstallPython($python_installer, $python_dir)
InstallJython($jython_installer, $jython_dir)
SetPath($python_dir, $jython_dir)  ; This must be done before InstallRobot to always have msvcrt71.dll in PATH
InstallRobot($robot_installer)
Exit

;;
;; Functions
;;

Func GetBaseDirectory()
    If $CmdLine[0] == 0 Then
        $base = InputBox("Robot Framework One Click Installer", $USAGE, "C:\", "", 500, 470)
    ElseIf $CmdLine[0] == 1 Then
        $base = $CmdLine[1]
    Else
        Cancel("Usage: " & @ScriptName & " [basedir]")
    EndIf
    If $base == "" Then
        Cancel("Installation cancelled by user.")
    ElseIf FileExists($base) == 0 Then
        Cancel("Given directory doesn't exist.")
    ElseIf StringRight($base, 1) <> "\" Then
        $base = $base & "\"
    EndIf
    Return $base
EndFunc

Func Cancel($msg)
    MsgBox(0, "Installation Cancelled", $msg)
    Exit
EndFunc

Func GetRequiredInstaller($pattern, $name)
    $installer = GetOptionalInstaller($pattern)
    If $installer == "" Then
        Cancel("Could not find " & $name & " installer with pattern '" & $pattern & "'")
    Endif
    return $installer
EndFunc

Func GetOptionalInstaller($pattern)
    $found = FileFindFirstFile($pattern)
    If $found == -1 Then
        $installer = ""
    Else
        $installer = FileFindNextFile($found)
    EndIf
    FileClose($found)
    return $installer
EndFunc

Func GetPythonDir($dir)
    VerifyInstallationDir($dir, "Python")
    return $dir
EndFunc

Func GetJythonDir($dir, $installer)
    If $installer == "" Then
        return ""
    EndIf
    VerifyInstallationDir($dir, "Jython")
    return $dir
EndFunc

Func VerifyInstallationDir($dir, $name)
    If FileExists($dir) == 1 Then
        Cancel($name & " installation directory '" & $dir & "' already exists.")
    EndIf
EndFunc

Func InstallPython($installer, $dir)
    $cmd = "msiexec /i " & $installer & " TARGETDIR=" & $dir & " /qb!"
    RunWait($cmd)
EndFunc

Func InstallJython($installer, $dir)
    If $installer == "" Then
        return
    EndIf
    $cmd = "java -jar " & $installer & " -s -d " & $dir
    RunWait($cmd)
EndFunc

Func InstallRobot($installer)
    Run($installer)
    WaitSetupWindowAndClickEnter("This Wizard will install")
    WaitSetupWindowAndClickEnter("Select python installation")
    WaitSetupWindowAndClickEnter("Ready to install")
    WaitSetupWindowAndClickEnter("Postinstall script finished")
EndFunc

Func WaitSetupWindowAndClickEnter($exp_text)
    WinWaitActive("Setup", $exp_text)
    Send("{ENTER}")
EndFunc

Func SetPath($python, $jython)
    $update = $python & ";" & $python & "\Scripts;" & $jython
    $orig = RegRead("HKCU\Environment", "PATH")

    If $orig == "" Then
        $new = $update
    ElseIf StringRight($orig, 1) == ";" Then
        $new = $orig & $update
    Else
        $new = $orig & ";" & $update
    EndIf

    RegWrite("HKCU\Environment", "PATH", "REG_EXPAND_SZ", $new)
    EnvUpdate()
EndFunc

;;  Copyright 2008 Nokia Siemens Networks Oyj
;;
;;  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.

;; Robot Framework One Click Installer for Windows
;;
;; This installer installs Robot Framework and its preconditions Python and
;; Jython (optional). If installer is executed without arguments, it opens a
;; dialog explaining the options and asking the user to enter the installation
;; directory. If a command line options is given, it must be a path to an
;; existing directory and it is used as installation directory.
;;
;; For more information about this script see $USAGE below. To learn more
;; about silent Python installation, see url [1]. Silent Jython installation
;; options can be seen with command [2].
;;
;; [1] http://www.python.org/download/releases/2.5/msi/#automated
;; [2] java -jar jython_installer-2.2.x.jar --help

;;
;; Config
;;

; Expected patterns for installer names and target directory names.
$PYTHON_DIR_NAME = "Python25"
$JYTHON_DIR_NAME = "Jython22"
$PYTHON_PATTERN = "python-2.5*.msi"
$ROBOT_PATTERN = "robot-1.8*.exe"
$JYTHON_PATTERN = "jython_installer-2.2*.jar"

; Usage to show to the user. If major versions of installed software are changed update them also here!!
; Patterns and directory names above are used in the usage so that they don't need to be updated.
$USAGE = "One Click Installer installs Robot Framework and its preconditions Python and Jython (optional). " & _
         "It also sets Robot start-up scripts (pybot, jybot, rebot) as well as Python and Jython executables " & _
         "into %PATH% environment variable so that they can be executed from the command line. (Note that " & _
         "you need to restart the command prompt for these changes to take effect.)" & @CRLF & @CRLF & _
		 "You should use this installer ONLY if you don't previously have Python or Jython installed. " & _
	     "In that case, and also if you want to have a custom installation, you need to install needed " & _
		 "components separately." & @CRLF & @CRLF & _
         "One Click Installer requires that you have all the required component installers in the same directory " & _
         "with it and that they have expected names. If Robot or Python installer is missing, " & _
         "installation fails. If Jython installer doesn't exist, Jython is simply not installed. Note that " & _
         "in order to install Jython, Java 1.4 or newer must be already installed. Supported " & _
         "versions are Robot 1.8.x, Python 2.5.x and Jython 2.2.x where '.x' means that any minor version " & _
         "(e.g. 1.8 or 1.8.3) is ok. These installers can be downloaded from respective project websites if " & _
         "they are missing. Expected patterns for installer names are '" & $ROBOT_PATTERN & "', '" & _
         $PYTHON_PATTERN & "' and '" & $JYTHON_PATTERN & "'." & @CRLF & @CRLF & _
         "The only thing you need to specify is the base directory where to install Python and Jython. " & _
         "They are installed into directories '" & $PYTHON_DIR_NAME & "' and '" & $JYTHON_DIR_NAME & "', " & _
         "respectively, inside the given base directory. Robot Framework itself is installed under Python " & _
         "installation directory and its startup scripts can be found from '[PYTHON]\Scripts' and code from " & _
         "'[PYTHON]\Lib\site-packages'." & @CRLF & @CRLF & _
         "Note that the specified base directory MUST exist and Python and Jython directories inside it must not. " & _
         "It is also not recommended to use a path containing spaces. Good candidates include directories like " & _
         "'C:\' and 'C:\APPS'."

;;
;; Main
;;

$base_dir = GetBaseDirectory()
$python_installer = GetRequiredInstaller($PYTHON_PATTERN, "Python")
$robot_installer = GetRequiredInstaller($ROBOT_PATTERN, "Robot")
$jython_installer = GetOptionalInstaller($JYTHON_PATTERN)
$python_dir = GetPythonDir($base_dir & "Python25")
$jython_dir = GetJythonDir($base_dir & "Jython22", $jython_installer)
InstallPython($python_installer, $python_dir)
InstallJython($jython_installer, $jython_dir)
SetPath($python_dir, $jython_dir)  ; This should be done before InstallRobot to get msvcrt71.dll into PATH
InstallRobot($robot_installer)
Exit

;;
;; Functions
;;

Func GetBaseDirectory()
	If $CmdLine[0] == 0 Then
		$base = InputBox("Robot Framework One Click Installer", $USAGE, "C:\", "", 500, 470)
	ElseIf $CmdLine[0] == 1 Then
		$base = $CmdLine[1]
	Else
		Cancel("Usage: " & @ScriptName & " [basedir]")
	EndIf
    If $base == "" Then
        Cancel("Installation cancelled by user.")
    ElseIf FileExists($base) == 0 Then
        Cancel("Given directory doesn't exist.")
    ElseIf StringRight($base, 1) <> "\" Then
        $base = $base & "\"
    EndIf
    Return $base
EndFunc

Func Cancel($msg)
    MsgBox(0, "Installation Cancelled", $msg)
    Exit
EndFunc

Func GetRequiredInstaller($pattern, $name)
    $installer = GetOptionalInstaller($pattern)
    If $installer == "" Then
        Cancel("Could not find " & $name & " installer with pattern '" & $pattern & "'")
    Endif
    return $installer
EndFunc

Func GetOptionalInstaller($pattern)
    $found = FileFindFirstFile($pattern)
    If $found == -1 Then
        $installer = ""
    Else
        $installer = FileFindNextFile($found)
    EndIf
    FileClose($found)
    return $installer
EndFunc

Func GetPythonDir($dir)
    VerifyInstallationDir($dir, "Python")
    return $dir
EndFunc

Func GetJythonDir($dir, $installer)
    If $installer == "" Then
        return ""
    EndIf
    VerifyInstallationDir($dir, "Jython")
    return $dir
EndFunc

Func VerifyInstallationDir($dir, $name)
    If FileExists($dir) == 1 Then
        Cancel($name & " installation directory '" & $dir & "' already exists.")
    EndIf
EndFunc

Func InstallPython($installer, $dir)
    $cmd = "msiexec /i " & $installer & " TARGETDIR=" & $dir & " /qb!"
    RunWait($cmd)
EndFunc

Func InstallJython($installer, $dir)
    If $installer == "" Then
        return
    EndIf
    $cmd = "java -jar " & $installer & " -s -d " & $dir
    RunWait($cmd)
EndFunc

Func InstallRobot($installer)
    Run($installer)
    WaitSetupWindowAndClickEnter("This Wizard will install")
    WaitSetupWindowAndClickEnter("Select python installation")
    WaitSetupWindowAndClickEnter("Ready to install")
    WaitSetupWindowAndClickEnter("Postinstall script finished")
EndFunc

Func WaitSetupWindowAndClickEnter($exp_text)
    WinWaitActive("Setup", $exp_text)
    Send("{ENTER}")
EndFunc

Func SetPath($python, $jython)
    $update = $python & ";" & $python & "\Scripts;" & $jython
    $orig = RegRead("HKCU\Environment", "PATH")

    If $orig == "" Then
        $new = $update
    ElseIf StringRight($orig, 1) == ";" Then
        $new = $orig & $update
    Else
        $new = $orig & ";" & $update
    EndIf

    RegWrite("HKCU\Environment", "PATH", "REG_EXPAND_SZ", $new)
    EnvUpdate()
EndFunc


Update daocstarter.au3

Update daocstarter.au3

redux au3

#NoTrayIcon
#include <Misc.au3>
#include <array.au3>
_Singleton(@ScriptName)
Global Const $VERSION = "1.0.0"
Global Const $DIST_ZIP_PATH = @AppDataDir & "\daocstarter\" & $VERSION; & "\daocstarter-win32-x64"
Global Const $WORKINGDIR = $DIST_ZIP_PATH & "\dist\daocstarter-win32-x64"
Global Const $EXE = $WORKINGDIR & "\daocstarter.exe"
Global Const $TMP_ZIP_PATH = @TempDir & "\dist.zip"
;~ DirRemove($DIST_ZIP_PATH, 1)

If Not FileExists($EXE) Then
	FileInstall(".\dist.zip", $TMP_ZIP_PATH, 1)
	_Zip_UnzipAll($TMP_ZIP_PATH, $DIST_ZIP_PATH & '\', 1);progress bar
EndIf
ShellExecute($EXE, "", $WORKINGDIR)

Func _Zip_UnzipAll($hZipFile, $hDestPath, $flag = 1)
	If _Zip_DllChk() <> 0 Then Return SetError(_Zip_DllChk(), 0, 0);no dll
	If Not FileExists($hZipFile) Then Return SetError(2, 0, 0) ;no zip file
	If Not FileExists($hDestPath) Then DirCreate($hDestPath)
	Local $aArray[1], $oApp = ObjCreate("Shell.Application")
	$oApp.Namespace($hDestPath).CopyHere($oApp.Namespace($hZipFile).Items)
	For $item In $oApp.Namespace($hZipFile).Items
		_ArrayAdd($aArray, $item)
	Next
	While 1
		If $flag = 1 then _Hide()
		If FileExists($hDestPath & "\" & $aArray[UBound($aArray) - 1]) Then Return SetError(0, 0, 1)
		Sleep(500)
	WEnd
EndFunc

Func _Zip_DllChk()
	If Not FileExists(@SystemDir & "\zipfldr.dll") Then Return 2
	If Not RegRead("HKEY_CLASSES_ROOT\CLSID\{E88DCCE0-B7B3-11d1-A9F0-00AA0060FA31}", "") Then Return 3
	Return 0
EndFunc

Func _Hide()
	If ControlGetHandle("[CLASS:#32770]", "", "[CLASS:SysAnimate32; INSTANCE:1]") <> "" And WinGetState("[CLASS:#32770]") <> @SW_HIDE	Then ;The Window Exists
		$hWnd = WinGetHandle("[CLASS:#32770]")
		WinSetState($hWnd, "", @SW_HIDE)
	EndIf
EndFunc

#NoTrayIcon
#include <Misc.au3>
#include <array.au3>
_Singleton(@ScriptName)
Global Const $VERSION = "1.0.0"
Global Const $DIST_ZIP_PATH = @AppDataDir & "\daocstarter\" & $VERSION; & "\daocstarter-win32-x64"
Global Const $WORKINGDIR = $DIST_ZIP_PATH & "\dist\daocstarter-win32-x64"
Global Const $EXE = $WORKINGDIR & "\daocstarter.exe"
Global Const $TMP_ZIP_PATH = @TempDir & "\dist.zip"
;~ DirRemove($DIST_ZIP_PATH, 1)

If Not FileExists($EXE) Then
	FileInstall(".\dist.zip", $TMP_ZIP_PATH, 1)
	_Zip_UnzipAll($TMP_ZIP_PATH, $DIST_ZIP_PATH & '\', 1);progress bar
EndIf
ShellExecute($EXE, "", $WORKINGDIR)

Func _Zip_UnzipAll($hZipFile, $hDestPath, $flag = 1)
	If _Zip_DllChk() <> 0 Then Return SetError(_Zip_DllChk(), 0, 0);no dll
	If Not FileExists($hZipFile) Then Return SetError(2, 0, 0) ;no zip file
	If Not FileExists($hDestPath) Then DirCreate($hDestPath)
	Local $aArray[1]
	$oApp = ObjCreate("Shell.Application")
	$oApp.Namespace($hDestPath).CopyHere($oApp.Namespace($hZipFile).Items)
	For $item In $oApp.Namespace($hZipFile).Items
		_ArrayAdd($aArray, $item)
	Next
	While 1
		If $flag = 1 then _Hide()
		If FileExists($hDestPath & "\" & $aArray[UBound($aArray) - 1]) Then
			Return SetError(0, 0, 1)
			ExitLoop
		EndIf
		Sleep(500)
	WEnd
EndFunc

Func _Zip_DllChk()
	If Not FileExists(@SystemDir & "\zipfldr.dll") Then Return 2
	If Not RegRead("HKEY_CLASSES_ROOT\CLSID\{E88DCCE0-B7B3-11d1-A9F0-00AA0060FA31}", "") Then Return 3
	Return 0
EndFunc

Func _Hide()
	If ControlGetHandle("[CLASS:#32770]", "", "[CLASS:SysAnimate32; INSTANCE:1]") <> "" And WinGetState("[CLASS:#32770]") <> @SW_HIDE	Then ;The Window Exists
		$hWnd = WinGetHandle("[CLASS:#32770]")
		WinSetState($hWnd, "", @SW_HIDE)
	EndIf
EndFunc


Update GuiCreateEx.au3

Update GuiCreateEx.au3

#include-once
#include <GuiCreateEx.au3> ; https://github.com/chechelaky/AutoIt/blob/master/GuiCreateEx/GuiCreateEx.au3

Global $hGui
Global $hButton_NewGui

$hGui = GUICreateEx("Título[ " & $g__aGuiCreateEx[0] & " ]", 800, 600)
$hButton_NewGui = GUICtrlCreateButton("new gui", 10, 10, 80, 20)
GUICtrlSetOnEvent($hButton_NewGui, "NewGui")
GUISetState(@SW_SHOW, $hGui)

While Sleep(25)
WEnd

Func NewGui()
	Local $aSize = WinGetPos($g__aGuiCreateEx[UBound($g__aGuiCreateEx, 1) - 1])
	Local $hGui = GUICreateEx("Título[ " & $g__aGuiCreateEx[0] & " ]", $aSize[2] - (20 + 6), $aSize[3] - (40 + 5), $aSize[0] + 10, $aSize[1] + 10, Default, Default, $g__aGuiCreateEx[UBound($g__aGuiCreateEx, 1) - 1])
	$hButton_NewGui = GUICtrlCreateButton("new gui", 10, 10, 80, 20)
	GUICtrlSetOnEvent($hButton_NewGui, "NewGui")
	GUISetState(@SW_SHOW, $hGui)
EndFunc   ;==>NewGui

#include-once
#include <Array.au3>
#include <GUIConstantsEx.au3>

OnAutoItExitRegister("_GUICreateEx_OnExit")

Opt("GUIOnEventMode", 1)
Opt("GUIEventOptions", 1)
Opt("MustDeclareVars", 1)

Global $g__aGuiCreateEx[1] = [0]

#cs
; Example
#include-once
#include <GuiCreateEx.au3>

Global $hGui
Global $hButton_NewGui

$hGui = GUICreateEx("Título[ " & $g__aGuiCreateEx[0] & " ]", 800, 600)
$hButton_NewGui = GUICtrlCreateButton("new gui", 10, 10, 80, 20)
GUICtrlSetOnEvent($hButton_NewGui, "NewGui")
GUISetState(@SW_SHOW, $hGui)

While Sleep(25)
WEnd

Func NewGui()
	Local $aSize = WinGetPos($g__aGuiCreateEx[UBound($g__aGuiCreateEx, 1) - 1])
	Local $hGui = GUICreateEx("Título[ " & $g__aGuiCreateEx[0] & " ]", $aSize[2] - (20 + 6), $aSize[3] - (40 + 5), $aSize[0] + 10, $aSize[1] + 10, Default, Default, $g__aGuiCreateEx[UBound($g__aGuiCreateEx, 1) - 1])
	$hButton_NewGui = GUICtrlCreateButton("new gui", 10, 10, 80, 20)
	GUICtrlSetOnEvent($hButton_NewGui, "NewGui")
	GUISetState(@SW_SHOW, $hGui)
EndFunc   ;==>NewGui
#ce

; #FUNCTION# ====================================================================================================================
; Name...........:	GUICreateEx
; Description ...:	Allow create a new GUI (Graphic User Interface) above current GUI and lock previus GUI
; Syntax.........:	same way of GuiCreate
; Parameters ....:	$sTitle.......: Title's GUI
;					$iWidth.......:	width's GUI
;					$iHeight......: height's GUI
;					$iLeft........:	left position's GUI
; 					$iTop.........: top position's GUI
;					$mStyle.......:	Style's GUI
;					$mExStyle.....:	Extended Style's GUI
;					$iParent......: The handle of another previously created window
; Return values .:	a windows handle
; Author ........:	Luismar Chechelaky
; Modified.......:	2015/06/20 11:25
; Remarks .......:
; Related .......:
; Link ..........:	https://github.com/chechelaky/AutoIt/raw/master/GuiCreateEx/GuiCreateEx.au3
; Example .......:
; ===============================================================================================================================
Func GUICreateEx($sTitle = "", $iWidth = 460, $iHeight = 360, $iLeft = -1, $iTop = -1, $mStyle = Default, $mExStyle = Default, $iParent = 0)
	If Not $g__aGuiCreateEx[0] Then
		$iParent = 0
	Else
		$iParent = $g__aGuiCreateEx[UBound($g__aGuiCreateEx, 1) - 1]
		GUISetState(@SW_DISABLE, $iParent)
	EndIf
	Local $hGui = GUICreate($sTitle, $iWidth, $iHeight, $iLeft, $iTop, $mStyle, $mExStyle, $iParent)
	If @error Then Return SetError(1, 0, 0)
	GUISetOnEvent($GUI_EVENT_CLOSE, "_GUICreateEx_Quit")
	_ArrayAdd($g__aGuiCreateEx, $hGui)
	$g__aGuiCreateEx[0] = UBound($g__aGuiCreateEx, 1) - 1
	Return $g__aGuiCreateEx[$g__aGuiCreateEx[0]]
EndFunc   ;==>GUICreateEx

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........:	_GUICreateEx_OnExit
; Author ........:	Luismar Chechelaky
; Modified.......:	2015/06/20 11:25
; Link ..........:	https://github.com/chechelaky/AutoIt/raw/master/GuiCreateEx/GuiCreateEx.au3
; ===============================================================================================================================
Func _GUICreateEx_OnExit()
	GUISetState($g__aGuiCreateEx[1], @SW_HIDE)
	GUIDelete($g__aGuiCreateEx[1])
EndFunc   ;==>_GUICreateEx_OnExit

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........:	_GUICreateEx_Quit
; Author ........:	Luismar Chechelaky
; Modified.......:	2015/06/20 11:25
; Link ..........:	https://github.com/chechelaky/AutoIt/raw/master/GuiCreateEx/GuiCreateEx.au3
; ===============================================================================================================================
Func _GUICreateEx_Quit()
	Local $hGui
	Switch $g__aGuiCreateEx[0]
		Case 1
			$hGui = $g__aGuiCreateEx[$g__aGuiCreateEx[0]]
			Exit
		Case Else
			GUISetState(@SW_ENABLE, $g__aGuiCreateEx[$g__aGuiCreateEx[0] - 1])
			GUISetState($g__aGuiCreateEx[$g__aGuiCreateEx[0]], @SW_HIDE)
			GUIDelete($g__aGuiCreateEx[$g__aGuiCreateEx[0]])
			_ArrayDelete($g__aGuiCreateEx, UBound($g__aGuiCreateEx, 1) - 1)
			$g__aGuiCreateEx[0] = UBound($g__aGuiCreateEx, 1) - 1
	EndSwitch
EndFunc   ;==>_GUICreateEx_Quit