Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.

Due to spam on this forum, all posts now need moderator approval.

 Entire forum ➜ MUSHclient ➜ Plugins ➜ Plugin to check if you have the latest version of MUSHclient

Plugin to check if you have the latest version of MUSHclient

It is now over 60 days since the last post. This thread is closed.     Refresh page


Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Sat 13 Nov 2010 06:29 AM (UTC)

Amended on Tue 16 Nov 2010 05:14 AM (UTC) by Nick Gammon

Message
The plugin below is designed to help you upgrade MUSHclient when new versions are released.

I am not a big fan of programs that constantly check back to base to see if there is a new version, partly because that is disclosing usage patterns and potentially private information.

However on the other hand, it can be annoying to have people post problem reports for problems which were fixed months ago.

This plugin is a compromise. It is completely optional whether or not you install it. If you do, it when MUSHclient loads it uses LuaSocket to get the contents of this web page:

http://www.mushclient.com/scripts/version.php

(Click on that link to see what it will get).

That page contains version information about the latest released version, in a format easily decoded by a Lua plugin (like this one).

If the plugin detects that your version is not the latest then it displays a miniwindow telling you about it, and giving you a hyperlink to download the latest version (installing it is still up to you).

Like this:



The last time you checked is recorded in the MUSHclient prefs file (I initially used a plugin state file, until I realized that you would be checking the version more often than required if you used multiple world files).

The version check is only done if 7 days have elapsed from the last check, so as to minimize both the time taken at your end, and the load on the web server. However you can manually check for the latest version by typing:


version_check


Any constructive comments are welcome.

Template:saveplugin=Version_Check To save and install the Version_Check plugin do this:
  1. Copy between the lines below (to the Clipboard)
  2. Open a text editor (such as Notepad) and paste the plugin into it
  3. Save to disk on your PC, preferably in your plugins directory, as Version_Check.xml
  4. Go to the MUSHclient File menu -> Plugins
  5. Click "Add"
  6. Choose the file Version_Check.xml (which you just saved in step 3) as a plugin
  7. Click "Close"



<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient>

<muclient>
<plugin
   name="Version_Check"
   author="Nick Gammon"
   id="2eb7301f3ac637b02a4467ef"
   language="Lua"
   purpose="Checks for a new version of MUSHclient"
   date_written="2010-11-13 16:45:58"
   requires="4.60"
   version="1.5"
   >
<description trim="y">
<![CDATA[
This automatically checks every week for a new version of MUSHclient.

It only checks when you load the plugin. You can change that by enabling the
timer in the plugin (change to: enabled="y" )

To check right now, type: version_check

]]>
</description>

</plugin>

<!--  Aliases  -->

<aliases>
  <alias
   name="check_version_now"
   script="do_version_check"
   match="version_check"
   enabled="y"
   sequence="100"
  >
  </alias>
</aliases>


<!--  Timers  -->

<timers>
  <timer name="version_check" 
         script="check_for_new_version" 
         enabled="n" 
         minute="30" 
         active_closed="y" 
   >

  </timer>
</timers>


<!--  Script  -->


<script>
<![CDATA[

-- interval

CHECK_INTERVAL = 60 * 60 * 24 * 7  -- every 7 days

-- font
FONT_NAME = "Microsoft Sans Serif"
FONT_SIZE = 10
font_id = "f"
font_id_bold = "fb"
font_id_underline = "fu"

MAX_WIDTH = 500
GAP = 5

TITLE = "A new version of MUSHclient is available."

VERSION_URL       = "http://www.mushclient.com/scripts/version.php";

ANNOUNCEMENTS_URL = "http://www.mushclient.com/scripts/?bbtopic_id=1";
RELNOTES_URL      = "http://www.mushclient.com/relnotes";

 
-- colours
WINDOW_BACKGROUND_COLOUR = ColourNameToRGB ("khaki")
WINDOW_TEXT_COLOUR = ColourNameToRGB ("black")
WINDOW_FRAME_COLOUR = ColourNameToRGB ("saddlebrown")
HYPERLINK_COLOUR = ColourNameToRGB ("mediumblue")

win = "version_info_" .. GetPluginID ()  -- get a unique name

-- find when we last checked the version number
db = sqlite3.open(GetInfo (82))  -- open preferences
          
 for row in db:nrows('SELECT * FROM prefs WHERE name = "time_last_version_check"') do
   last_check_time = tonumber (row.value)
 end

 -- if not in database, insert row
 if not last_check_time then
   db:exec 'INSERT INTO prefs (name, value) VALUES ("time_last_version_check", 0)'
   last_check_time = 0
 end -- if
  
db:close()  -- close

function hyperlink_download ()
   OpenBrowser (installer_url)
end -- hyperlink_download 

function hyperlink_announcements ()
   OpenBrowser (ANNOUNCEMENTS_URL)
end -- hyperlink_announcements 

function hyperlink_relnotes ()
   OpenBrowser (RELNOTES_URL)
end -- hyperlink_relnotes 

function hyperlink_close ()
   WindowShow (win, false)
end -- hyperlink_close 

-- here if they click on the hyperlink
function mouseup (flags, hotspotid)
  local f = hyperlink_functions [hotspotid]
  if f then
    f ()
  end -- function found
end -- mouseup

hyperlink_functions = {}

function make_hyperlink (text, id, left, top, action, hint)

  -- work out text rectangle size
  local height = WindowFontInfo (win, font_id, 1)  
  local right = left + WindowTextWidth (win, font_id, text)
  local bottom = top + height

  -- add the hotspot
  WindowAddHotspot(win, id,  
                   left, top, right, bottom, 
                   "", -- mouseover (do nothing)
                   "", -- cancelmouseover (do nothing)
                   "", -- mousedown (do nothing)
                   "", -- cancelmousedown (do nothing)
                   "mouseup", -- mouseup
                   hint,    -- hint text if they hover over it              
                   miniwin.cursor_hand, 0)
  

  -- draw the hyperlink text in the rectangle                   
  WindowText (win, font_id_underline, text, left, top, right, bottom, HYPERLINK_COLOUR)               
  
  -- remember action function
  hyperlink_functions [id] = action  
           
end -- make_hyperlink    

function do_version_check ()
  
  require "getlines"
  require "movewindow"
  
  if package.loaders [3] == nil or package.loadlib == nil then
     ColourNote ("orange", "", GetPluginName () .. " cannot do version check.") 
     ColourNote ("orange", "", "You need to allow DLLs to be loaded.")
     ColourNote ("orange", "", "You also need to trust this plugin.")
     ColourNote ("orange", "", "See File Menu -> Global Preferences -> Lua")
     return
  end -- if
    
  local http = require "socket.http" 
  
  SetStatus "Checking for latest MUSHclient version ..."
  local page =  http.request (string.format ("%s?plat=%i,%i,%i&vers=%s",
                              VERSION_URL, 
                              GetInfo (268), GetInfo (265), GetInfo (266),
                              Version ()))
  SetStatus "Ready"
  
  if not page then return end -- page doesn't exist
  
  local s = string.match (page, "<pre>(.*)</pre>")
  
  if not s then return end  -- page in wrong format
  
  local t = {}  
  setfenv (assert (loadstring (s)), t) () -- compile and load into t
  
  local info = t.installer_info
  
  if not info then return end  -- installer_info not there
  
  local new_version = tonumber (info.version)
  local old_version = tonumber (Version ())
  
  -- naive version check (chuckle)
  if new_version <= old_version then
    ColourNote ("cyan", "", "You have version " .. Version () .. 
                " of MUSHclient, which is the lastest version.")
    return  -- have latest version
  end -- if
  
  -- make the window to get font info
  WindowCreate (win, 0, 0, 0, 0, -- very small
                miniwin.pos_center_all, 0, 
                WINDOW_BACKGROUND_COLOUR)  -- create window
                 
  local Charset = miniwin.font_charset_default
  local PitchAndFamily = miniwin.font_family_swiss + miniwin.font_pitch_variable
  
  -- grab fonts
  WindowFont (win, font_id,           FONT_NAME, FONT_SIZE, false, false, false, false, Charset, PitchAndFamily) 
  WindowFont (win, font_id_bold,      FONT_NAME, FONT_SIZE, true,  false, false, false, Charset, PitchAndFamily )
  WindowFont (win, font_id_underline, FONT_NAME, FONT_SIZE, false, false, true,  false, Charset, PitchAndFamily) 
  
  -- work out how high a font line is
  font_height = WindowFontInfo (win, font_id, 1)   -- height of the font  
  
  -- interim window width
  window_width = WindowTextWidth (win, font_id_bold, TITLE)
  lines = {}
  
  -- wrap long lines
  for line in getlines (info.description) do
    local width = 0
    local t = {}
    
    for word in string.gmatch (line, "%S+") do
      word = word .. " "  -- put one space back
      local word_width = WindowTextWidth (win, font_id, word)
      
      -- too wide with this word, finish off previous line, start new one
      if (width + word_width) > MAX_WIDTH then
        table.insert (lines, table.concat (t))
        t = {}
        table.insert (t, "   ")  -- indent wrapped line
        width = WindowTextWidth (win, font_id, t [1])
      end -- if
      table.insert (t, word)
      width = width + word_width
    end -- for each word (ie. something not spaces)
    
    -- finish previous line
    table.insert (lines, table.concat (t))
  end -- for

  -- find maximum line width
  for _, line in ipairs (lines) do
    window_width = math.max (window_width, WindowTextWidth (win, font_id, line))
  end -- for
    
  -- 10 fixed lines, plus the description lines
  window_height = 10 + (11 + #lines) * font_height 
  window_width = window_width + GAP + GAP  -- 5 pixel margin each side
  
  -- install the window movement handler, get back the window position
  windowinfo = movewindow.install (win, miniwin.pos_center_all)
  
  -- make the "real" window
  WindowCreate (win, 0, 0, window_width, window_height, miniwin.pos_center_all, 0, 
                           WINDOW_BACKGROUND_COLOUR)  -- create window
  
  -- title box
  WindowRectOp (win, miniwin.rect_fill, 0, 0, 0, font_height + GAP, ColourNameToRGB "tan")
  
  -- frame it                           
  WindowRectOp (win, miniwin.rect_frame, 0, 0, 0, 0, WINDOW_FRAME_COLOUR )
  
  -- add the drag handler so they can move the window around
  movewindow.add_drag_handler (win, 0, 0, 0, font_height + GAP)
  
  -- left margin
  x = GAP
  
  -- top margin
  y = GAP
  
  WindowText (win, font_id_bold, TITLE, x, y, 0, 0, WINDOW_TEXT_COLOUR )
  y = y + font_height
  
  WindowText (win, font_id, "Current version: " .. Version (), x, y, 0, 0, WINDOW_TEXT_COLOUR )
  y = y + font_height
  
  WindowText (win, font_id, "Available version: " .. new_version, x, y, 0, 0, WINDOW_TEXT_COLOUR )
  y = y + font_height
  
  WindowText (win, font_id, string.format ("Size: %0.2f Mb", info.installer_size / 1024 / 1024), x, y, 0, 0, WINDOW_TEXT_COLOUR )
  y = y + font_height
 
  installer_url = info.installer_url 
  
  -- link to download this version
  make_hyperlink ("Download version " .. new_version, 
                  "download", 
                  x, y, hyperlink_download, "Download version " .. new_version)
  y = y + font_height
  
  -- link to view announcements forum topic
  make_hyperlink ("Visit announcements forum topic", "announcements", x, y, hyperlink_announcements, "View announcements")
  y = y + font_height

  -- link to view all release notes
  make_hyperlink ("View all release notes", "relnotes", x, y, hyperlink_relnotes, "View release notes")
  y = y + font_height

  -- extra line 
  y = y + font_height
  
  WindowText (win, font_id_bold, "Improvements:", x, y, 0, 0, WINDOW_TEXT_COLOUR )
  y = y + font_height
  
  -- extra line
  y = y + font_height
  
  -- show description  
  for _, line in ipairs (lines) do
    WindowText (win, font_id, line, x, y, 0, 0, WINDOW_TEXT_COLOUR )
    y = y + font_height
  end -- for
  
  make_hyperlink ("Close this window", "close", x, y, hyperlink_close, "Close notification window")
  y = y + font_height

  -- close box
  local box_size = font_height - 2
  x = GAP
  y = GAP
  local box_colour = 0x404040
  WindowRectOp (win, miniwin.rect_frame, 
                x + window_width - box_size - GAP * 2, 
                y, 
                x + window_width - GAP * 2, 
                y + box_size, 
                box_colour)
  WindowLine (win, x + window_width - box_size - GAP * 2 + 3, 
                   y + 3, 
                   x + window_width - GAP * 2 - 3, 
                   y - 3 + box_size, 
                   box_colour, 
                   miniwin.pen_solid, 1)
  WindowLine (win, x - 4 + window_width - GAP * 2, 
                   y + 3, 
                   x - 1 + window_width - box_size - GAP * 2 + 3, 
                   y - 3 + box_size, 
                   box_colour, 
                   miniwin.pen_solid, 1)
  
  -- close configuration hotspot               
  WindowAddHotspot(win, "close_box",  
                   x + window_width - box_size - GAP * 2, 
                   y, 
                   x + window_width - GAP * 2, 
                   y + box_size,   
                   "", "", "", "", 
                   "hyperlink_close",  -- mouseup
                   "Click to close",
                   miniwin.cursor_hand, 0)  -- hand cursor
  
  -- show the window
  WindowShow (win, true)
    
  -- we last checked: now
  last_check_time = os.time ()
  
  -- remember when we checked last
  db = sqlite3.open(GetInfo (82))  -- open preferences
  db:exec (string.format ('UPDATE prefs SET value = %i WHERE name = "time_last_version_check"',
            last_check_time))
  db:close()  -- close

end -- do_version_check

function check_for_new_version (name)

  -- don't check too often or it will slow us down
  if os.time () < (last_check_time + CHECK_INTERVAL) then
    return
  end -- too soon
     
  do_version_check () -- check now
  
end -- check_for_new_version

-- check for time to check for new version when loaded, 
-- and then every 30 minutes if timer enabled
check_for_new_version ()

]]>
</script>

</muclient>



[EDIT]

Version 1.1 - fixed problem with semicolons added by forum.

Version 1.2 - allowed for long announcement lines - now wraps them at a reasonable width. Added hyperlink to see all release notes.

Version 1.3 - added a "close box" on the top RH corner.

Version 1.4 - fixed bug where it always said you needed a new version (left in for testing). Also it sends your current version and Windows platform to the web server.

Version 1.5 - fixed to check if DLLs can be loaded (otherwise it can't get the version data)

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Hunter Green   USA  (16 posts)  Bio
Date Reply #1 on Sat 13 Nov 2010 12:19 PM (UTC)
Message
Apologies if I'm just misunderstanding something about it, but when I try to add the plugin I get this error:

[string "Plugin"]:94: ')' expected near ';'

[WARNING] C:\Program Files\MUSHclient\worlds\plugins\Version_Check.xml
Line 65: Error parsing script (Cannot load)

Am I doing something wrong?
Top

Posted by Crowe   (21 posts)  Bio
Date Reply #2 on Sat 13 Nov 2010 01:13 PM (UTC)
Message
I got this when trying to add/load the above plugin. I have version 4.69.

Compile error
Plugin: Version_Check (called from world: Aardwolf)
Immediate execution
[string "Plugin"]:94: ')' expected near ';'
Error context in script:
90 :
91 : local http = require "socket.http"
92 :
93 : SetStatus "Checking for latest MUSHclient version ..."
94*: local page = http.request ("http://www.mushclient.com/scripts/version.php";;)
95 : SetStatus "Ready"
96 :
97 : if not page then return end -- page doesn't exist
98 :
[WARNING] F:\Personal Files\MUD Files\Scripts\Version_Check.xml
Line 65: Error parsing script (Cannot load)
Top

Posted by Hunter Green   USA  (16 posts)  Bio
Date Reply #3 on Sat 13 Nov 2010 01:24 PM (UTC)

Amended on Sat 13 Nov 2010 01:26 PM (UTC) by Hunter Green

Message
Deleting that semicolon on that line only changes it to this:

C:\Program Files\MUSHclient\lua\socket.lua:13: module 'socket.core' not found:
no field package.preload['socket.core']
no file '.\socket\core.lua'
no file 'C:\Program Files\MUSHclient\lua\socket\core.lua'
no file 'C:\Program Files\MUSHclient\lua\socket\core\init.lua'
no file 'C:\Program Files\MUSHclient\socket\core.lua'
no file 'C:\Program Files\MUSHclient\socket\core\init.lua'
stack traceback:
[C]: in function 'require'
C:\Program Files\MUSHclient\lua\socket.lua:13: in main chunk
[C]: in function 'require'
.\socket\http.lua:11: in main chunk
[C]: in function 'require'
[string "Plugin"]:91: in function 'do_version_check'
[string "Plugin"]:227: in function 'check_for_new_version'
[string "Plugin"]:233: in main chunk

Makes me think I have something else unset or not installed that everyone else already has set up.
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #4 on Sat 13 Nov 2010 06:45 PM (UTC)
Message
The forum was adding a semicolon to what it thought was hyperlinks. I rejigged it slightly so the semicolon won't matter.

As for the "module 'socket.core' not found:" you need LuaSocket which came out with version 4.60.

Since the plugin requires version 4.60 that should work, unless you fiddled with the required version number.

I just tested on my Windows 7 install which had version 4.67 installed, and that seemed to work OK.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #5 on Sat 13 Nov 2010 07:41 PM (UTC)
Message
Updated to version 1.2 to allow for wrapping long announcement lines. Also changed the font, and added a better title bar. It now looks like this:



(This was a test image, normally the version numbers would differ, and the release notes are made up to test the wrapping).

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #6 on Sat 13 Nov 2010 07:44 PM (UTC)
Message
There is a brief pause while the plugin gets the version information, because the grabbing of the web page is done synchronously. This is one reason why it is only done occasionally.

You might also consider adding this plugin as a "global plugin" (see File -> Global Preferences) so the check is done regardless of which world (or character) you are currently playing.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Hunter Green   USA  (16 posts)  Bio
Date Reply #7 on Sat 13 Nov 2010 10:40 PM (UTC)
Message
Still get the Socket error. I'm running 4.69, installed via the installer. I haven't done anything at all with plugins in this installation before this; as far as I know this is pretty nearly a virgin install and the world file I'm loading is very simple.

There is a socket directory in C:\Progam Files\MUSHclient, and it has a core.dll file in it, but not a core.lua file which seems to be what the plugin is asking for. (Also in that directory: ftp.lua, http.lua, smtp.lua, tp.lua, and url.lua.)

After a bit of searching, I found this thread:
http://www.gammon.com.au/forum/?id=8319&page=999
About two thirds of the way down Candido had the same problem. You directed him to check an item on the Global Preferences dialog's Lua tab to allow DLLs to load. Once I did that, it works. So that's the missing piece.
Top

Posted by LezChap   (36 posts)  Bio
Date Reply #8 on Sun 14 Nov 2010 03:09 AM (UTC)
Message
Nick Gammon said:

There is a brief pause while the plugin gets the version information, because the grabbing of the web page is done synchronously. This is one reason why it is only done occasionally.

You might also consider adding this plugin as a "global plugin" (see File -> Global Preferences) so the check is done regardless of which world (or character) you are currently playing.



Couldn't you run it in a coroutine, and make it so it doesn't "freeze" while downloading the web page? Something along the lines of the example here: http://www.lua.org/pil/9.4.html

Another possible solution is including LuaLanes with MushClient...though I don't know how you feel about adding a more things like that.
Top

Posted by Twisol   USA  (2,257 posts)  Bio
Date Reply #9 on Sun 14 Nov 2010 04:38 AM (UTC)
Message
Creating an interface for "workers", a la the WebWorkers proposal, would certainly be cool. Since JavaScript has traditionally been single-threaded as well, anyone interested in developing this would be wise to follow in the WHATWG's footsteps.

'Soludra' on Achaea

Blog: http://jonathan.com/
GitHub: http://github.com/Twisol
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #10 on Sun 14 Nov 2010 05:13 AM (UTC)
Message
LezChap said:

Couldn't you run it in a coroutine, and make it so it doesn't "freeze" while downloading the web page? Something along the lines of the example here: http://www.lua.org/pil/9.4.html


Yes, very possibly.

At this stage it is really a proof of concept, whipped up in afternoon. If it seems well-accepted, then I could look at removing the slight delay while it runs. Bear in mind that I find that (unlike many programs) MUSHclient starts, connects to a MUD, and is ready to use in, say, one second. The extra delay, of about a second, once a week, whilst annoying, is hardly overly onerous.

Potentially I might find that, if the version check runs without any noticeable delay, then hundreds of thousands of users will configure it to run every five minutes, which will cause quite a hit on the web site.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #11 on Tue 16 Nov 2010 05:05 AM (UTC)
Message
Hunter Green said:

Still get the Socket error. I'm running 4.69, installed via the installer. I haven't done anything at all with plugins in this installation before this; as far as I know this is pretty nearly a virgin install and the world file I'm loading is very simple.
...

You directed him to check an item on the Global Preferences dialog's Lua tab to allow DLLs to load. Once I did that, it works. So that's the missing piece.


Yes I just got the same problem under Ubuntu. For this plugin to work you have to be able to load DLLs. Also make sure that the Lua sandbox (global preferences) is the less-restrictive one described in http://www.gammon.com.au/security

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #12 on Tue 16 Nov 2010 05:14 AM (UTC)
Message
I amended the plugin to check if DLLs can be loaded by the Lua sandbox. That should replace the error message with something more informative.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


38,843 views.

It is now over 60 days since the last post. This thread is closed.     Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.