It is currently April 16th, 2024, 2:14 pm

Reader

Discuss the use of Lua in Script measures.
User avatar
Kaelri
Developer
Posts: 1721
Joined: July 25th, 2009, 4:47 am

Reader

Post by Kaelri »

Evereader0.4Preview.png
Reader is a script that parses any RSS, Atom, Google Calendar or Remember the Milk web feed. You don't need to know any Lua to use the script; you can drop it into any skin and start using it right now.

Get The Script

Place the Reader.lua script file somewhere in your skin folder.
Reader.zip
How It Works

Here's the simplest way to add Reader to your skin:

Code: Select all

[MyWebParser]
Measure=Plugin
Plugin=WebParser
UpdateRate=600
Url=http://rainmeter.net/forum/feed.php
RegExp=(?siU)(.*)$
FinishAction=!CommandMeasure MyReader Refresh()

[MyReader]
Measure=Script
ScriptFile=Reader.lua
MeasureName=MyWebParser
On WebParser, the URL must be a valid RSS or Atom feed. The RegExp provided here will grab the entire contents of the feed. The FinishAction will tell the script to refresh whenever WebParser does, so they'll always stay in sync. On Reader, all you need is a MeasureName that points back to the WebParser measure.

What It Does

The script creates dynamic variables for all the feed metadata:
  • FeedTitle: the title of the feed (or "Untitled", if no title is found).
  • FeedLink: the main feed link.
  • CurrentFeed: the number of the current-displayed feed (in the order given in MeasureName).

And for each item, where "N" is the item number:
  • ItemNTitle: the title of the item (or "Untitled").
  • ItemNLink: the item link (or the main feed link, or blank).
  • ItemNDesc: the item description/summary (or blank).
  • ItemNDate: the item date. Format can be set for Google Calendar feeds. See Timestamp below.
  • ItemNUnread: "1" if the item is marked unread, "0" if marked read. There are three bangs to change an item's "Unread" state:
    • !CommandMeasure MeasureName MarkRead(N) will mark the given item as read, changing #ItemNUnread# to 0.
    • !CommandMeasure MeasureName MarkUnread(N) will mark the given item as unread (1).
    • !CommandMeasure MeasureName ToggleUnread(N) will toggle the item between read (0) and unread (1).
You can use these variables anywhere in the skin. Example:

Code: Select all

[Item3]
Meter=STRING
Text=#Item3Title#
LeftMouseUpAction=["#Item3Link#"][!CommandMeasure MyReader MarkRead(3)]
ToolTipText=#Item3Desc#
DynamicVariables=1
Multiple Feeds

The script is able to keep track of feeds from multiple WebParser measures:

Code: Select all

[MyWebParser1]
Measure=Plugin
Plugin=WebParser
UpdateRate=600
Url=http://rainmeter.net/forum/feed.php
RegExp=(?siU)(.*)$
FinishAction=!CommandMeasure MyReader Refresh(1)

[MyWebParser2]
Measure=Plugin
Plugin=WebParser
UpdateRate=600
Url=http://feeds.gawker.com/lifehacker/excerpts.xml
RegExp=(?siU)(.*)$
FinishAction=!CommandMeasure MyReader Refresh(2)

[MyReader]
Measure=Script
ScriptFile=Reader.lua
MeasureName=MyWebParser1|MyWebParser2
The MeasureName option contains each WebParser's measure name, separated by pipes (|). The FinishAction on each WebParser allows the feed to update in the background, which makes switching feeds faster.

There are three bangs you can use to change which feed is displayed:
  • !CommandMeasure MeasureName ShowNext(): show the next feed. Loops around to the first feed.
  • !CommandMeasure MeasureName ShowPrevious(): show the previous feed. Loops around to the last feed.
  • !CommandMeasure MeasureName Show(N): show feed #N.
Example:

Code: Select all

[BackArrow]
Meter=Button
ButtonCommand=!CommandMeasure MyReader ShowPrevious()

[Tab1]
Meter=Button
ButtonCommand=!CommandMeasure MyReader Show(1)

[Tab2]
Meter=Button
ButtonCommand=!CommandMeasure MyReader Show(2)

[Tab3]
Meter=Button
ButtonCommand=!CommandMeasure MyReader Show(3)

[ForwardArrow]
Meter=Button
ButtonCommand=!CommandMeasure MyReader ShowNext()
Multiple Scripts

Code: Select all

[MyReader2]
Measure=Script
ScriptFile=Reader.lua
MeasureName=MyWebParser1

[MyReader2]
Measure=Script
ScriptFile=Reader.lua
MeasureName=MyWebParser2
VariablePrefix=Group2_
If you want to show multiple feeds at the same time, just add another Reader script measure. You can have any number of Readers running in the same skin. To make sure they don't conflict with each other, the VariablePrefix option will add an extra label to the front of every variable that the script creates. For example, if VariablePrefix=Group2_, the variables will be named "Group2_FeedTitle", "Group2_FeedLink", "Group2_Item1Title", etc.

Minimum and Maximum Items

Code: Select all

[MyReader]
Measure=Script
ScriptFile=Reader.lua
MeasureName=MyWebParser1
MinItems=10
MaxItems=100
The optional MinItems sets the minimum number of items to create variables for. For example, if your skin has 10 item meters, but the feed only has 5 items, setting MinItems=10 will make items 6-10 show as blank. This will also stop items from one feed getting "stuck" if you switch to another feed with fewer items.

The optional MaxItems sets the maximum number of items in the database for each feed. If there are ever more items than the maximum, the oldest ones are discarded to make room for the newest ones. This is meant for putting a limit on the number of items that are saved in the history file (see below).

FinishAction

Code: Select all

[MyReader]
Measure=Script
ScriptFile=Reader.lua
MeasureName=MyWebParser1
FinishAction=[!UpdateMeterGroup ListOfItems][!Redraw]
The optional FinishAction can be any bang. It will execute whenever the currently-showing feed is updated, and whenever you switch feeds. It can be changed with !SetOption MeasureName FinishAction """!Bang""".

You can use the FinishAction for anything you want. I like to have it update the item meters, which makes the feeds show up a little quicker when the skin loads (see the example above).

Timestamp

Code: Select all

[MyReader]
Measure=Script
ScriptFile=Reader.lua
Timestamp=%I.%M %p
The optional Timestamp is used to format event dates for Google Calendar items. (Other formats are not supported yet; this is a work-in-progress.) Formats may be written using Lua timestamp tags:

Code: Select all

%a	abbreviated weekday name (e.g., Wed)
%A	full weekday name (e.g., Wednesday)
%b	abbreviated month name (e.g., Sep)
%B	full month name (e.g., September)
%c	date and time (e.g., 09/16/98 23:48:10)
%d	day of the month (16) [01-31]
%H	hour, using a 24-hour clock (23) [00-23]
%I	hour, using a 12-hour clock (11) [01-12]
%M	minute (48) [00-59]
%m	month (09) [01-12]
%p	either "am" or "pm" (pm)
%S	second (10) [00-61]
%w	weekday (3) [0-6 = Sunday-Saturday]
%x	date (e.g., 09/16/98)
%X	time (e.g., 23:48:10)
%Y	full year (1998)
%y	two-digit year (98) [00-99]
%%	the character `%´
KeepOldItems

Code: Select all

[MyReader]
Measure=Script
ScriptFile=Reader.lua
MeasureName=MyWebParser1
KeepOldItems=1
If KeepOldItems=1 is set, items are kept in the database even if they are no longer found in the feed file. This is a very powerful feature when combined with WriteHistory (below). It can be turned on or off with !SetOption MeasureName KeepOldItems [1/0].

Calendar Events

Code: Select all

[MyReader]
Measure=Script
ScriptFile=Reader.lua
MeasureName=MyWebParser1|MyWebParser2
WriteEvents=1
;EventFile=Calendar1.xml|Calendar2.xml
If WriteEvents=1 is set, items found in Google Calendar feeds will be saved to a file. The "event file" is compatible with LuaCalendar, Enigma, and possibly more. Writing can be turned on or off with !SetOption MeasureName WriteEvents [1/0].

The EventFile option contains the filenames for each feed. If there are multiple feeds, each file is separated by a pipe, just as in MeasureName. If a feed's file is not defined, it defaults to "MeasureName_FeedNEvents.xml" in the local folder. Events are only written if the feed is in the Google Calendar format.

History

Code: Select all

[MyReader]
Measure=Script
ScriptFile=Reader.lua
MeasureName=MyWebParser1|MyWebParser2
WriteHistory=1
;HistoryFile=MyHistoryFile.xml
If WriteHistory=1 is set, the entire list of items from all feeds is saved to a file. The file is updated instantly whenever a feed is refreshed, or an item is marked as read/unread. When the skin is loaded or refreshed, Reader will add items from the history file back into the database. In other words, the "state" is always saved between sessions, including items that you have marked as read. Writing can be turned on or off with !SetOption MeasureName WriteHistory [1/0].

History is saved by feed URL, so it doesn't matter if you change the order of the feeds, or remove a feed and then re-add it at a later time. In addition, if KeepOldItems (above) is enabled, older items will be permanently saved. For this reason, you may want to set a MaxItems limit (see above) to keep the history file from growing too large and slowing down the skin.

You can also wipe your history with !CommandMeasure MeasureName ClearHistory(), which deletes the history file and instantly refreshes the skin.

Demo Skin
Evereader_0.4.rmskin
Credits

Credit is due to JSMorley, who helped conceive the original version of this script, and Smurfier, who contributed the calendar file feature and numerous other fixes and improvements.
You do not have the required permissions to view the files attached to this post.
User avatar
smurfier
Moderator
Posts: 1931
Joined: January 29th, 2010, 1:43 am
Location: Willmar, MN

Re: [Proof of Concept] Universal Feed Reader

Post by smurfier »

Wow...

So, it creates the variables even if they don't already exist in the ini?
GitHub | DeviantArt | Tumblr
This is the song that never ends. It just goes on and on my friends. Some people started singing it not knowing what it was, and they'll continue singing it forever just because . . .
User avatar
Kaelri
Developer
Posts: 1721
Joined: July 25th, 2009, 4:47 am

Re: [Proof of Concept] Universal Feed Reader

Post by Kaelri »

Yep! !SetVariable doesn't require variables to be hard-coded.
User avatar
smurfier
Moderator
Posts: 1931
Joined: January 29th, 2010, 1:43 am
Location: Willmar, MN

Re: [Proof of Concept] Universal Feed Reader

Post by smurfier »

O.O World...turning...upside down...
GitHub | DeviantArt | Tumblr
This is the song that never ends. It just goes on and on my friends. Some people started singing it not knowing what it was, and they'll continue singing it forever just because . . .
User avatar
Kaelri
Developer
Posts: 1721
Joined: July 25th, 2009, 4:47 am

Re: [Proof of Concept] Universal Feed Reader

Post by Kaelri »

Do that for another 8 hours, and you'll be where I am now. :)
User avatar
KreAch3R
Posts: 608
Joined: February 7th, 2011, 7:27 pm
Location: Thessaloniki, GR

Re: [Proof of Concept] Universal Feed Reader

Post by KreAch3R »

Ok, I don't understand anything lua behind it (haven't digged in it), but I just tried it with a feed that didn't worked in other readers and worked perfectly! :) Nice breakthrough Kaelri :thumbup: :thumbup:
Inactive, due to life changes. Send me a PM for any question.

Desktop DeviartArt
Image
User avatar
jsmorley
Developer
Posts: 22629
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: [Proof of Concept] Universal Feed Reader

Post by jsmorley »

Great, great job Kaelri...

Let's be honest folks. I didn't "help" much here. Kaleri and I dug into this together with my nOOb ranking only a point or two less than his, and it was far more a "two heads are better than one" thing in a few tricky spots than any "tutelage". We both learned a lot while we cursed and laughed...

This is all Kaelri... Great concept, great execution.
poiru
Developer
Posts: 2872
Joined: April 17th, 2009, 12:18 pm

Re: [Proof of Concept] Universal Feed Reader

Post by poiru »

smurfier wrote:O.O World...turning...upside down...
Your world is going to implode this Sunday :)
User avatar
jsmorley
Developer
Posts: 22629
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: [Proof of Concept] Universal Feed Reader

Post by jsmorley »

Sunday should be fun...

Image
User avatar
Kaelri
Developer
Posts: 1721
Joined: July 25th, 2009, 4:47 am

Re: [Proof of Concept] Universal Feed Reader

Post by Kaelri »

Updated to add support for multiple instances of the script. You can now parse and return variables for any number of feeds simultaneously. This is accomplished by setting a "prefix" on new instances to make sure they don't conflict. For example:

Code: Select all

[MeasureLuaScript]
Measure=Script
ScriptFile="#CURRENTPATH#Evereader.lua"
FeedMeasureName=MeasureFeed

[List2.MeasureLuaScript]
Measure=Script
ScriptFile="#CURRENTPATH#Evereader.lua"
FeedMeasureName=MeasureFeed2
VariablePrefix=List2.
The first measure will create #ItemTitle1#, #ItemLink1#, #ItemTitle2#, etc. from [MeasureFeed], as expected.

The second measure will create #List2.ItemTitle1#, #List2.ItemLink1#, #List2.ItemTitle2#, etc. from [MeasureFeed2].

You can also use the "switcher" for multiple feeds on each instance, using the same prefix to set the variables:

Code: Select all

[Variables]
NumberOfFeeds=3
FeedMeasureName1=MeasureFeed
FeedMeasureName2=MeasureFeed2
FeedMeasureName3=MeasureFeed3
CurrentFeed=1

List2.NumberOfFeeds=3
List2.FeedMeasureName1=MeasureFeed4
List2.FeedMeasureName2=MeasureFeed5
List2.FeedMeasureName3=MeasureFeed6
List2.CurrentFeed=1

[MeasureLuaScript]
Measure=Script
ScriptFile="#CURRENTPATH#Evereader.lua"
MultipleFeeds=1

[List2.MeasureLuaScript]
Measure=Script
ScriptFile="#CURRENTPATH#Evereader.lua"
MultipleFeeds=1
VariablePrefix=List2.
Which would (or could) be used for something like this:



I also increased the UpdateDivider in the example skin, just for improved efficiency. If you do the same in your skins, you'll want to add

Code: Select all

FinishAction=!CommandMeasure "MeasureLuaScript" "Update()"
to your WebParser measures, as well as your switcher buttons, to make sure the variables are always updated when they need to be.

I'm beginning to work on adding additional feed item data, such as description, author, pub date, etc. This is tricky because those tags aren't always provided, and the method I'd like to use as a fail-safe is causing the script to choke on big feeds like Google News. I'll keep experimenting.

I'm also going to add a function to switch to the next or previous feed when triggered with a !Command Measure.