<commit_before>--[[
--------------------------------------------------

Update Checker for Rainmeter
v5.0.0
By raiguard

Modified form of 'semver.lua' by kikito (https://github.com/kikito/semver.lua)
Implements 'JSON.lua' by rxi (https://github.com/rxi/json.lua)

--------------------------------------------------

Release Notes:
v5.0.0 - 2018-7-2:
- Switched to use GitHub REST v3 API, rather than a customized INI file
v4.1.0 - 2018-6-21:
- Switched to using the WebParser measure output rather than a downloaded file
  for the ReadINI function
v4.0.0 - 2018-??-??:
- Removed hard-coded actions and replaced with arguments in the script measure
- Implemented "semver.lua" for more robust comparisons
- Switched to using INI format for the remote version data
- Added 'GetIniValue' function for retrieving other information from remote
v3.0.0 - 2018-??-??:
- Added support for update checking on development versions
v2.1.0 - 2018-??-??:
- Fixed oversight where if the user is on a development version for an
  outdated release, it would not return UpdateAvailable()
- Added 'ParsingError' return
v2.0.0 - 2018-??-??:
- Removed dependancy on an output meter in favor of hard-coded actions, added
  more documentation
v1.0.1 - 2018-??-??:
- Optimized gmatch function, more debug functionality
v1.0.0 - 2018-??-??:
- Initial release

--------------------------------------------------

This script takes

Please keep in mind that version strings must be formatted using the Semantic
Versioning 2.0.0 format. See http://semver.org/ for additional information.

--------------------------------------------------

INSTRUCTIONS FOR USE:

[MeasureUpdateCheckerScript]
Measure=Script
Script=#@#Scripts\UpdateChecker.lua
CheckForPrereleases=#checkForPrereleases#
UpToDateAction=[!ShowMeter "UpToDateString"]
DevAction=[!ShowMeter "DevString"]
UpdateAvailableAction=[!ShowMeter "UpdateAvailableString"]
ParsingErrorAction=[!ShowMeter "ParsingErrorString"]

This is an example of the script measure you will use to invoke this script.
The 'CheckForPrereleases' defines whether the update checker will compare
with the most recent full release, or the most recent release whatsoever.
Each action option is a series of bangs to execute when that outcome is
reached by the comparison function.

[MeasureUpdateCheck]
Measure=WebParser
URL=#webParserUrl#
RegExp=(?siU)^(.*)$
StringIndex=1
UpdateRate=#updateCheckRate#
OnConnectErrorAction=[!Log "Couldn't connect to update server" "Error"]
FinishAction=[!CommandMeasure MeasureUpdateCheckerScript "CheckForUpdate('#version#', 'MeasureUpdateCheck')"]
DynamicVariables=1

This is an example of the webparser measure used to download the information.
The important thing to note here is the last argument on the 'FinishAction'
line. This must be the name of the WebParser measure, whatever that may
be. This allows the script to actually retrieve the string that was downloaded,
which lets the update check actually take place.

The script retrieves the raw JSON data from the GitHub API, then uses a JSON
parser function to convert it into a LUA table. From there, the script extracts
data for the most recent full release, and the most recent release regardless
of whether or not it is a prerelease. Which release is compared to and provides
the release information is determined by the 'CheckForPrereleases' option in the
script measure.

There are four values for each release that you can retrieve for displaying in
your skin. Each value is retrieved using
[&MeasureUpdateCheckerScript:GetReleaseInfo('key')]. Replace key with one of the
following options:

'name' - returns the tag version of the release
'date' - returns the published date of the release
'changelog' - returns the release's changelog, with the release version and
              published date added to the beginning
'downloadUrl' - returns the URL that can be used to download the .RMSKIN
                attached to the release

--------------------------------------------------
]]--

debug = false

function Initialize()

  upToDateAction = SELF:GetOption('UpToDateAction')
  updateAvailableAction = SELF:GetOption('UpdateAvailableAction')
  parsingErrorAction = SELF:GetOption('ParsingErrorAction')
  devAction = SELF:GetOption('DevAction')
  checkForPrereleases = tonumber(SELF:GetOption('CheckForPrereleases', '1'))
  if devAction == '' or devAction == nil then devAction = upToDateAction end
  printIndent = ' '
  releases = {}

end

function Update() end

function CheckForUpdate(cVersion, measureName)


  showPrereleases = tonumber(SELF:GetOption('ShowPrereleases', 1))
  apiJson = json.decode(SKIN:GetMeasure(measureName or 'MeasureUpdateCheck'):GetStringValue())
  releases = AssembleReleaseInfo(apiJson)

  Compare(cVersion, releases[checkForPrereleases + 1]['name'])

end

-- compares two semver-formatted version strings
function Compare(cVersion, rVersion)

  cVersion = v(cVersion)
  rVersion = v(rVersion)
  if cVersion == rVersion then
    LogHelper('Up-to-date', 'Debug')
    SKIN:Bang(upToDateAction)
  elseif cVersion > rVersion then
    LogHelper('Development version', 'Debug')
    SKIN:Bang(devAction)
  elseif cVersion < rVersion then
    LogHelper('Update available', 'Debug')
    SKIN:Bang(updateAvailableAction)
  else
    LogHelper('Parsing error', 'Debug')
    SKIN:Bang(parsingErrorAction)
  end

end

function GetReleaseInfo(key)
  return releases[checkForPrereleases + 1] and releases[checkForPrereleases + 1][key] or '---'
end

function AssembleReleaseInfo(jsonTable)

  local releases = {}

  local i = 0
  local k = 0
  while i == 0 do
    k = k + 1
    if jsonTable[k]['prerelease'] == false then
      i = 1
      releases[1] = {}
      releases[1]['name'] = jsonTable[k]['tag_name']:gsub('v', '')
      releases[1]['date'] = jsonTable[k]['published_at']:gsub('(.*)T(.*)', '%1')
      releases[1]['changelog'] = 'v' .. releases[1]['name'] .. ' - ' .. releases[1]['date'] .. '\n' .. jsonTable[k]['body']:gsub('\r\n', '\n')
      releases[1]['downloadUrl'] = jsonTable[k]['assets'][1]['browser_download_url']
    end
  end

  releases[2] = {}
  releases[2]['name'] = jsonTable[1]['tag_name']:gsub('v', '')
  releases[2]['date'] = jsonTable[1]['published_at']:gsub('(.*)T(.*)', '%1')
  releases[2]['changelog'] = 'v' .. releases[2]['name'] .. ' - ' .. releases[2]['date'] .. ':\n' .. jsonTable[1]['body']:gsub('\r\n', '\n')
  releases[2]['downloadUrl'] = jsonTable[1]['assets'][1]['browser_download_url']
  return releases

end

-- function to make logging messages less cluttered
function LogHelper(message, type)<commit_msg>Update checker 6.1.0<commit_after>--[[
--------------------------------------------------

Update Checker for Rainmeter
v6.1.0
By raiguard

Implements 'semver.lua' by kikito (https://github.com/kikito/semver.lua)
Implements 'JSON.lua' by rxi (https://github.com/rxi/json.lua)

--------------------------------------------------

Release Notes:
v6.1.0 - 2018-7-4
- Added 'RawChangelog' option
v6.0.0 - 2018-7-2
- Switched to use GitHub REST v3 API, rather than a customized INI file
v5.1.0 - 2018-6-21
- Switched to using the WebParser measure output rather than a downloaded file
  for the ReadINI function
v5.0.0 - 2017-12-20
- Removed hard-coded actions and replaced with arguments in the script measure
- Switched to using INI format for the remote version data
- Added 'GetIniValue' function for retrieving other information from remote
v4.0.0 - 2016-11-18
- Implemented "semver.lua" for more robust comparisons
v3.0.0 - 2016-11-14
- Added support for update checking on development versions
v2.1.0 - 2016-11-14
- Fixed oversight where if the user is on a development version for an
  outdated release, it would not return UpdateAvailable()
- Added 'ParsingError' return
v2.0.0 - 2016-8-4
- Removed dependancy on an output meter in favor of hard-coded actions, added
  more documentation
v1.0.1 - 2016-7-1
- Optimized gmatch function, more debug functionality
v1.0.0 - 2016-1-25
- Initial release

--------------------------------------------------

This script compares two semver-formatted version strings and compares them,
returning whether the current version is outdated, up-to-date, or a development
version. By default, it uses the GitHub REST API to download release information,
automatically extracting the most recent release from the specified repository.
However, you do not need to use this if you have another method for retrieving
the most recently released version.

Please keep in mind that version strings must be formatted using the Semantic
Versioning 2.0.0 format. See http://semver.org/ for additional information.

--------------------------------------------------

INSTRUCTIONS FOR USE:

[MeasureUpdateCheckerScript]
Measure=Script
Script=#@#Scripts\UpdateChecker.lua
CheckForPrereleases=#checkForPrereleases#
UpToDateAction=[!ShowMeter "UpToDateString"]
DevAction=[!ShowMeter "DevString"]
UpdateAvailableAction=[!ShowMeter "UpdateAvailableString"]
ParsingErrorAction=[!ShowMeter "ParsingErrorString"]

This is an example of the script measure you will use to invoke this script.
The 'CheckForPrereleases' defines whether the update checker will compare
with the most recent full release, or the most recent release whatsoever.
Each action option is a series of bangs to execute when that outcome is
reached by the comparison function.

[MeasureUpdateCheck]
Measure=WebParser
URL=#webParserUrl#
RegExp=(?siU)^(.*)$
StringIndex=1
UpdateRate=#updateCheckRate#
OnConnectErrorAction=[!Log "Couldn't connect to update server" "Error"]
FinishAction=[!CommandMeasure MeasureUpdateCheckerScript "CheckForUpdate('#version#', 'MeasureUpdateCheck')"]
DynamicVariables=1

This is an example of the webparser measure used to download the information.
The important thing to note here is the last argument on the 'FinishAction'
line. This must be the name of the WebParser measure, whatever that may
be. This allows the script to actually retrieve the string that was downloaded,
which lets the update check actually take place.

The script retrieves the raw JSON data from the GitHub API, then uses a JSON
parser function to convert it into a LUA table. From there, the script extracts
data for the most recent full release, and the most recent release regardless
of whether or not it is a prerelease. Which release is compared to and provides
the release information is determined by the 'CheckForPrereleases' option in the
script measure.

There are four values for each release that you can retrieve for displaying in
your skin. Each value is retrieved using
[&MeasureUpdateCheckerScript:GetReleaseInfo('key')]. Replace key with one of the
following options:

'name' - returns the tag version of the release
'date' - returns the published date of the release
'changelog' - returns the release's changelog, with the release version and
              published date added to the beginning
'downloadUrl' - returns the URL that can be used to download the .RMSKIN
                attached to the release

Please note that any meter that extracts information from the script in this way
will need 'DynamicVariables=1' set in order to function properly.

By default, the changelog will include the release's tag version and published
date attached to the beginning of the string. If you wish to disable this, add
'RawChangelog=1' to the script measure.

--------------------------------------------------
]]--

debug = false

function Initialize()

  upToDateAction = SELF:GetOption('UpToDateAction')
  updateAvailableAction = SELF:GetOption('UpdateAvailableAction')
  parsingErrorAction = SELF:GetOption('ParsingErrorAction')
  devAction = SELF:GetOption('DevAction')
  rawChangelog = tonumber(SELF:GetOption('RawChangelog', '0'))
  checkForPrereleases = tonumber(SELF:GetOption('CheckForPrereleases', '1'))
  if devAction == '' or devAction == nil then devAction = upToDateAction end
  printIndent = ' '
  releases = {}

end

function Update() end

function CheckForUpdate(cVersion, measureName)

  showPrereleases = tonumber(SELF:GetOption('ShowPrereleases', 1))
  apiJson = json.decode(SKIN:GetMeasure(measureName or 'MeasureUpdateCheck'):GetStringValue())
  releases = AssembleReleaseInfo(apiJson)

  Compare(cVersion, releases[checkForPrereleases + 1]['name'])

end

-- compares two semver-formatted version strings
function Compare(cVersion, rVersion)

  cVersion = v(cVersion)
  rVersion = v(rVersion)
  if cVersion == rVersion then
    LogHelper('Up-to-date', 'Debug')
    SKIN:Bang(upToDateAction)
  elseif cVersion > rVersion then
    LogHelper('Development version', 'Debug')
    SKIN:Bang(devAction)
  elseif cVersion < rVersion then
    LogHelper('Update available', 'Debug')
    SKIN:Bang(updateAvailableAction)
  else
    LogHelper('Parsing error', 'Debug')
    SKIN:Bang(parsingErrorAction)
  end

end

function GetReleaseInfo(key)
  return releases[checkForPrereleases + 1] and releases[checkForPrereleases + 1][key] or '---'
end

function AssembleReleaseInfo(jsonTable)

  local releases = {}

  local i = 0
  local k = 0
  while i == 0 do
    k = k + 1
    if jsonTable[k]['prerelease'] == false then
      i = 1
      releases[1] = {}
      releases[1]['name'] = jsonTable[k]['tag_name']:gsub('v', '')
      releases[1]['date'] = jsonTable[k]['published_at']:gsub('(.*)T(.*)', '%1')
      releases[1]['changelog'] = (rawChangelog == 0 and  'v' .. releases[1]['name'] .. ' - ' .. releases[1]['date'] .. '\n' or '') .. jsonTable[k]['body']:gsub('\r\n', '\n')
      releases[1]['downloadUrl'] = jsonTable[k]['assets'][1]['browser_download_url']
    end
  end

  releases[2] = {}
  releases[2]['name'] = jsonTable[1]['tag_name']:gsub('v', '')
  releases[2]['date'] = jsonTable[1]['published_at']:gsub('(.*)T(.*)', '%1')
  releases[2]['changelog'] = (rawChangelog == 0 and  'v' .. releases[2]['name'] .. ' - ' .. releases[2]['date'] .. '\n' or '') .. jsonTable[1]['body']:gsub('\r\n', '\n')
  releases[2]['downloadUrl'] = jsonTable[1]['assets'][1]['browser_download_url']
  return releases

end

-- function to make logging messages less cluttered
function LogHelper(message, type)
{'fraction_non_alphanumeric': 0.14024996449367988, 'fraction_numerical': 0.017824172702741087, 'mean_word_length': 3.9001391788448156, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 21, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3518540', 'n_tokens_mistral': 4226, 'n_tokens_neox': 3979, 'n_words': 1417}