Newsline

About

Newsline is a news reader which appears as a horizontal bar and is intended to be utilized with feeds that are expected to be updated at a higher frequency, mostly announcements, issue trackers, forums, geographical (e.g. weather) and vehicle traffic data.

magdesgn: OLIMEX Teres-I (olimex-teres i) | Knuxify: Category:mutantCybernetics | FlashTeens: Category:SudoMaker | Knuxify: Category:Troubleshooting | Avron: Troubleshooting : RE: How to install Guix Package Manager? | emily: I packaged tangara-companion for Arch | jacqueline: Documentation on manual flashing + recovery | sam: Troubleshooting : Some of iceweasel's security features may offer less protection on your current... | summermusic: How to reset or recover from broken software state? | sam: Troubleshooting : How to install Guix Package Manager? | ayumi: Gentoo Ebuild for Tangara Companion Application | sam: Troubleshooting : How to install Guix Package Manager? | Schimon presents Blasta, a PubSub bookmarks system and Rivista, a PubSub Dynamic Site Generator | Stephen Paul Weber: What is WebXDC? | Kaidan and Zerocat | Daniel Gultsch: "Der Angriff auf jabber.ru und mögliche Gegenmaßnahmen" | sch: XMPP as a platform to synchronize data |

Preview

Preview

Features

  • Parse Atom, RDF and RSS feeds;

  • Filter items by keywords;

  • Scroll items.

Future Features

  • Atom Over XMPP (PubSub);

  • Configuration script.

Requirements

  • Conky

  • Python

Recommendations

This bar is namrly intended to be utilized on "box" desktops, such as AwesomeWM, Blackbox, dwm, Fluxbox, FVWM, Hyprland, i3, Openbox, Sway, SXMO etc., yet it is functional on Budgie, LXDE, LXQt, MATE, Trinity and Xfce desktops as well.

Code

newsline.conkyrc

conky.config = {
-- CORE
   background = true,
   update_interval = 20,
   total_run_times = 0,

   cpu_avg_samples = 2,
   net_avg_samples = 2,

   double_buffer = true,
-- no_buffers = true,

   template0 = '\n',

-- COLOURS
   default_color = '#000',
-- own_window_argb_value = 70,
-- own_window_argb_visual = true,
   own_window_colour = '#dfdfdf',

-- DIMENSIONS
-- minimum_height = 10,
-- minimum_size = 300,
   minimum_width = 1920,
   maximum_width = 1920,

-- GRAPHICS
   draw_borders = false,
   draw_graph_borders = false,
   draw_outline = false,
   draw_shades = false,
   short_units,

-- POSITION
   alignment = 'bottom_middle',

-- DISPLAY MONITOR
-- xinerama_head = 2,

-- TEXT
   font = 'DejaVu Sans Mono:size=17',
   override_utf8_locale = true,
   uppercase = false,
   use_xft = true,
-- xftfont = 'Montserrat Regular:size=16',

-- TYPE
   own_window = true,
   own_window_class = 'NewsLine',
   own_window_hints = undecorated,above,sticky,skip_taskbar,skip_pager,
   own_window_title = newsline,
   own_window_transparent = no,
   own_window_type = 'dock', -- for blackbox, fluxbox, i3 (top) and openbox
-- own_window_type = 'panel', -- for i3 (bottom), xfce
-- own_window_type = 'override', -- for xfce
}

conky.text = [[${scroll left 250 10 20 ${execpi 600 python newsline.py}}]]

newsline.py

import feedparser
import re
import sys
import toml

def strip_html_tags(text):
    clean = re.compile('<.*?>')
    return re.sub(clean, '', text)

def is_listed(entry, keywords):
    for keyword in keywords:
        for property in ['author', 'content', 'summary', 'title']:
            if property in entry:
                if isinstance(entry[property], list):
                    entry_property = ' '
                    for content in entry[property]:
                        if 'value' in entry[property]: entry_property += entry[property]['value']
                    entry[property] = entry_property
                if keyword.lower() in entry[property].lower():
                    return True

if __name__ == '__main__':
    excerpts = []
    toml_file = toml.load('newsline.toml')
    max_titles = toml_file['titles']
    blacklist = toml_file['blacklist']
    whitelist = toml_file['whitelist']
    for url in toml_file['sources']:
        try:
            feed = feedparser.parse(url)
        except Exception as e:
            print(f"Error parsing {url}: {e}", file=sys.stderr)
            feed = None
        if feed:
            data = []
            for entry in feed.entries:
                # Set whitelisted and blacklisted to False.
                blacklisted = whitelisted = False
                # Check whether a whitelisted keyword exists.
                whitelisted = is_listed(entry, whitelist)
                # If entry is not whitelisted, check whether a blacklisted keyword exists.
                if not whitelisted: blacklisted = is_listed(entry, blacklist)
                # If entry is not blacklisted, add it to the list.
                if not blacklisted:
                    info = {'title' : strip_html_tags(entry['title']) if 'title' in entry else 'No title',
                            'author' : strip_html_tags(entry['author']) if 'author' in entry else '',
                            'updated' : entry['updated'] if 'updated' in entry else ''}
                    data.append(info)
                    if len(data) > max_titles: break
            excerpt = data
        else:
            excerpt = []
        excerpts += excerpt
    # Sort entries by date.
    sorted_excerpts = sorted(excerpts, key=lambda x: x['updated'], reverse=True)
    excerpt_text = ''
    # Concatenate entries
    for excerpt in sorted_excerpts:
        if excerpt['author']:
            excerpt_text += f"{excerpt['author']}: {excerpt['title']} | "
        else:
            excerpt_text += f"{excerpt['title']} | "
    # Replace characters that may disrupt rendering by Conky.
    excerpt_text = excerpt_text.replace('#', '№')
    print(excerpt_text)
    sys.exit()

newsline.toml

# Set the amount of titles per source
titles = 3

# Feed URLs
sources = [
    "https://forum.cooltech.zone/syndication.php?type=atom1.0",
    "https://forums.rockbox.org/index.php?type=atom;action=.xml",
    "https://gitlab.archlinux.org/archlinux/packaging/packages/linux/-/issues.atom",
    "https://salsa.debian.org/Mobian-team.atom",
    "https://wiki.postmarketos.org/index.php?title=Special:RecentChanges&feed=atom",
]

# Filters
blacklist = ['goog', 'hmd', 'lobal', 'micros', 'noki', 'buntu']
whitelist = ['2780', '8110', 'argon', 'magdesign', 'weeknd']