mirror of
				https://github.com/Clortox/rss-cli.git
				synced 2025-07-17 14:12:11 +00:00 
			
		
		
		
	Add output for rss items
This commit is contained in:
		
							parent
							
								
									f028458841
								
							
						
					
					
						commit
						95e822bbc6
					
				@ -10,4 +10,4 @@
 | 
			
		||||
 * Set to 1 to compile and run the test suite
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define _TESTS_ 1
 | 
			
		||||
#define _TESTS_ 0
 | 
			
		||||
 | 
			
		||||
@ -32,11 +32,16 @@ int main(int argc, char** argv) {
 | 
			
		||||
    if(!feed.isOk())
 | 
			
		||||
        exit(-1);
 | 
			
		||||
 | 
			
		||||
    //display requested attributes
 | 
			
		||||
 | 
			
		||||
    //display requested attributes and items
 | 
			
		||||
    std::string output = rss_utils::rss_to_list(feed, opts);
 | 
			
		||||
 | 
			
		||||
    std::cout << output << std::endl;
 | 
			
		||||
    if(opts->items != nullptr){
 | 
			
		||||
        feed.getItems();
 | 
			
		||||
        output += "\n" + rss_utils::rss_to_items(feed, opts);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::cout << output << std::endl;
 | 
			
		||||
 | 
			
		||||
    delete opts;
 | 
			
		||||
    return 0;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										135
									
								
								src/options.cpp
									
									
									
									
									
								
							
							
						
						
									
										135
									
								
								src/options.cpp
									
									
									
									
									
								
							@ -7,29 +7,49 @@
 | 
			
		||||
#include "options.hpp"
 | 
			
		||||
 | 
			
		||||
void help(char* progName){
 | 
			
		||||
    std::cout << "Usage: " << progName << " [-u FEED_URI]\n";
 | 
			
		||||
    std::cout << "Usage: " << progName << " [-u FEED_URI] [CHANNEL FLAGS] ";
 | 
			
		||||
    std::cout << "[-i ITEM_INDEX] [ITEM FLAGS]\n";
 | 
			
		||||
    std::cout << "Options:\n";
 | 
			
		||||
    std::cout << "Required Options:\n";
 | 
			
		||||
    std::cout << " [-u, --uri]            URI of the rss stream\n\n";
 | 
			
		||||
    std::cout << " [-u, --uri] URI        URI of the rss stream\n\n";
 | 
			
		||||
 | 
			
		||||
    std::cout << "Channel information:\n";
 | 
			
		||||
    std::cout << " [-t, --title]          Get title of channel\n";
 | 
			
		||||
    std::cout << " [-l, --link]           Get link to channel\n";
 | 
			
		||||
    std::cout << " [-d, --description]    Get Description of channel\n";
 | 
			
		||||
    std::cout << " [-d, --description]    Get description of channel\n";
 | 
			
		||||
    std::cout << " [-e, --language]       Get language code of channel\n";
 | 
			
		||||
    std::cout << " [-m, --webmaster]      Get webMaster's email\n";
 | 
			
		||||
    std::cout << " [-c, --copyright]      Get copyright\n";
 | 
			
		||||
    std::cout << " [-p, --pubdate]        Get publishing date\n";
 | 
			
		||||
    std::cout << " [-q, --managingeditor] Get Managing Editor\n";
 | 
			
		||||
    std::cout << " [-q, --managingeditor] Get managing editor\n";
 | 
			
		||||
    std::cout << " [-g, --generator]      Get generator of this feed\n";
 | 
			
		||||
    std::cout << " [-o, --docs]           Get link to RSS documentation\n";
 | 
			
		||||
    std::cout << " [-w, --ttl]            Get ttl, time that channel can be\n";
 | 
			
		||||
    std::cout << "                        cached before being updated\n";
 | 
			
		||||
    std::cout << " [-b, --builddate]      Get last time the channel's\n";
 | 
			
		||||
    std::cout << "                        content changed\n\n";
 | 
			
		||||
    std::cout << "                        content changed\n";
 | 
			
		||||
    std::cout << " [-i, --item] INDEX     Provide index of item to display\n";
 | 
			
		||||
    std::cout << "                        If no index is provided, assume the first\n";
 | 
			
		||||
    std::cout << "                        item in the feed. All following flags will\n";
 | 
			
		||||
    std::cout << "                        be parsed as item options, till another\n";
 | 
			
		||||
    std::cout << "                        item is provided\n\n";
 | 
			
		||||
 | 
			
		||||
    std::cout << "Item options:\n";
 | 
			
		||||
    std::cout << " [-t, --title]          Get title of item\n";
 | 
			
		||||
    std::cout << " [-l, --link]           Get link\n";
 | 
			
		||||
    std::cout << " [-d, --description]    Get description\n";
 | 
			
		||||
    std::cout << " [-a, --author]         Get author\n";
 | 
			
		||||
    std::cout << " [-z, --category]       Get category list\n";
 | 
			
		||||
    std::cout << " [-f, --comments]       Get link to comments\n";
 | 
			
		||||
    std::cout << " [-j, --guid]           Get GUID\n";
 | 
			
		||||
    std::cout << " [-p, --pubdate]        Get publishing date\n";
 | 
			
		||||
    std::cout << " [-s, --source]         Get source of item\n\n";
 | 
			
		||||
 | 
			
		||||
    std::cout << "General options:\n";
 | 
			
		||||
    std::cout << " [-h, --help]           Show this message\n";
 | 
			
		||||
    std::cout << " [-h, --help]           Show this message\n\n";
 | 
			
		||||
 | 
			
		||||
    std::cout << "For more information, refer to the RSS 2.0 documentation\n";
 | 
			
		||||
    std::cout << "https://validator.w3.org/feed/docs/rss2.html\n";
 | 
			
		||||
 | 
			
		||||
    exit(1);
 | 
			
		||||
}
 | 
			
		||||
@ -37,8 +57,13 @@ void help(char* progName){
 | 
			
		||||
option_flags* parse_options(int argc, char** argv) {
 | 
			
		||||
    int option_index = 0;
 | 
			
		||||
    int c;
 | 
			
		||||
 | 
			
		||||
    item_flags* current_item = nullptr;
 | 
			
		||||
    option_flags* ret = new option_flags;
 | 
			
		||||
 | 
			
		||||
    ret->item_count = 0;
 | 
			
		||||
    ret->items = nullptr;
 | 
			
		||||
 | 
			
		||||
    while(true){
 | 
			
		||||
        c = getopt_long(argc, argv, optarg_string, 
 | 
			
		||||
                long_options, &option_index);
 | 
			
		||||
@ -50,13 +75,22 @@ option_flags* parse_options(int argc, char** argv) {
 | 
			
		||||
                ret->uri = std::string(optarg);
 | 
			
		||||
                break;
 | 
			
		||||
            case 't':
 | 
			
		||||
                ret->title ^= 1;
 | 
			
		||||
                if(current_item == nullptr)
 | 
			
		||||
                    ret->title ^= 1;
 | 
			
		||||
                else
 | 
			
		||||
                    current_item->title ^= 1;
 | 
			
		||||
                break;
 | 
			
		||||
            case 'l':
 | 
			
		||||
                ret->link ^= 1;
 | 
			
		||||
                if(current_item == nullptr)
 | 
			
		||||
                    ret->link ^= 1;
 | 
			
		||||
                else
 | 
			
		||||
                    current_item->link ^= 1;
 | 
			
		||||
                break;
 | 
			
		||||
            case 'd':
 | 
			
		||||
                ret->description ^= 1;
 | 
			
		||||
                if(current_item == nullptr)
 | 
			
		||||
                    ret->description ^= 1;
 | 
			
		||||
                else
 | 
			
		||||
                    current_item->description ^= 1;
 | 
			
		||||
                break;
 | 
			
		||||
            case 'e':
 | 
			
		||||
                ret->language ^= 1;
 | 
			
		||||
@ -68,7 +102,10 @@ option_flags* parse_options(int argc, char** argv) {
 | 
			
		||||
                ret->copyright ^= 1;
 | 
			
		||||
                break;
 | 
			
		||||
            case 'p':
 | 
			
		||||
                ret->pubdate ^= 1;
 | 
			
		||||
                if(current_item == nullptr)
 | 
			
		||||
                    ret->pubdate ^= 1;
 | 
			
		||||
                else
 | 
			
		||||
                    current_item->pubdate ^= 1;
 | 
			
		||||
                break;
 | 
			
		||||
            case 'q':
 | 
			
		||||
                ret->managingeditor ^= 1;
 | 
			
		||||
@ -85,7 +122,85 @@ option_flags* parse_options(int argc, char** argv) {
 | 
			
		||||
            case 'b':
 | 
			
		||||
                ret->builddate ^= 1;
 | 
			
		||||
                break;
 | 
			
		||||
            case 'i':
 | 
			
		||||
                if(ret->items == nullptr){
 | 
			
		||||
                    ret->items = new item_flags[ret->item_count + 1];
 | 
			
		||||
                    current_item = &(ret->items[0]);
 | 
			
		||||
                    ret->item_count++;
 | 
			
		||||
                    current_item->index = optarg ? atoi(optarg) : 0;
 | 
			
		||||
                } else {
 | 
			
		||||
                    item_flags* new_flags = new item_flags[ret->item_count + 1];
 | 
			
		||||
                    for(unsigned int i=0;i<ret->item_count;++i)
 | 
			
		||||
                        new_flags[i] = ret->items[i];
 | 
			
		||||
                    delete ret->items;
 | 
			
		||||
                    ret->items = new_flags;
 | 
			
		||||
                    current_item = &(ret->items[ret->item_count]);
 | 
			
		||||
                    ret->item_count++;
 | 
			
		||||
                    current_item->index = optarg ? atoi(optarg) : 0;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case 'a':
 | 
			
		||||
                if(current_item == nullptr){
 | 
			
		||||
                    std::cerr << "Invalid option in this context: [-a --author]" << std::endl;
 | 
			
		||||
                    std::cerr << "Did you provide the [-i --index] flag first?" << std::endl;
 | 
			
		||||
                } else
 | 
			
		||||
                    current_item->author ^= 1;
 | 
			
		||||
                break;
 | 
			
		||||
            case 'z':
 | 
			
		||||
                if(current_item == nullptr){
 | 
			
		||||
                    std::cerr << "Invalid option in this context: [-z --category]" << std::endl;
 | 
			
		||||
                    std::cerr << "Did you provide the [-i --index] flag first?" << std::endl;
 | 
			
		||||
                } else
 | 
			
		||||
                    current_item->category ^= 1;
 | 
			
		||||
                break;
 | 
			
		||||
            case 'f':
 | 
			
		||||
                if(current_item == nullptr){
 | 
			
		||||
                    std::cerr << "Invalid option in this context: [-f --comments]" << std::endl;
 | 
			
		||||
                    std::cerr << "Did you provide the [-i --index] flag first?" << std::endl;
 | 
			
		||||
                } else
 | 
			
		||||
                    current_item->comments ^= 1;
 | 
			
		||||
                break;
 | 
			
		||||
            case 'j':
 | 
			
		||||
                if(current_item == nullptr){
 | 
			
		||||
                    std::cerr << "Invalid option in this context: [-j --guid]" << std::endl;
 | 
			
		||||
                    std::cerr << "Did you provide the [-i --index] flag first?" << std::endl;
 | 
			
		||||
                } else
 | 
			
		||||
                    current_item->guid ^= 1;
 | 
			
		||||
                break;
 | 
			
		||||
            case 's':
 | 
			
		||||
                if(current_item == nullptr){
 | 
			
		||||
                    std::cerr << "Invalid option in this context: [-s --source]" << std::endl;
 | 
			
		||||
                    std::cerr << "Did you provide the [-i --index] flag first?" << std::endl;
 | 
			
		||||
                } else
 | 
			
		||||
                    current_item->source ^= 1;
 | 
			
		||||
                break;
 | 
			
		||||
            case ':': //go here if flag that requires argument is passed, but no arg given
 | 
			
		||||
                switch(optopt){
 | 
			
		||||
                    case 'i':
 | 
			
		||||
                        if(ret->items == nullptr){
 | 
			
		||||
                            ret->item_count++;
 | 
			
		||||
                            ret->items = new item_flags[ret->item_count];
 | 
			
		||||
                            current_item = &(ret->items[0]);
 | 
			
		||||
                            current_item->index = 1;
 | 
			
		||||
                        } else {
 | 
			
		||||
                            item_flags* new_flags = new item_flags[ret->item_count + 1];
 | 
			
		||||
                            for(unsigned int i=0;i<ret->item_count;++i)
 | 
			
		||||
                                new_flags[i] = ret->items[i];
 | 
			
		||||
                            delete ret->items;
 | 
			
		||||
                            ret->items = new_flags;
 | 
			
		||||
                            current_item = &(ret->items[ret->item_count]);
 | 
			
		||||
                            ret->item_count++;
 | 
			
		||||
                            current_item->index = 1;
 | 
			
		||||
                        }
 | 
			
		||||
                        break;
 | 
			
		||||
                    default:
 | 
			
		||||
                        std::cerr << "Invalid use: option -" << (char)optopt 
 | 
			
		||||
                            << " requires an argument" << std::endl;
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case '?':
 | 
			
		||||
                std::cerr << "Unknown option: " << (char)optopt << std::endl;
 | 
			
		||||
            case 'h':
 | 
			
		||||
                help(argv[0]);
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
@ -11,11 +11,12 @@
 | 
			
		||||
#include <getopt.h>
 | 
			
		||||
 | 
			
		||||
//cli options
 | 
			
		||||
constexpr char optarg_string[] = "u:tldemcpqgowbh";
 | 
			
		||||
constexpr char optarg_string[] = ":u:tldemcpqgowbi::azfjsh";
 | 
			
		||||
 | 
			
		||||
static struct option long_options[] =
 | 
			
		||||
{
 | 
			
		||||
    {"uri",   required_argument,    0, 'u'},
 | 
			
		||||
 | 
			
		||||
    {"title", no_argument,          0, 't'},
 | 
			
		||||
    {"link",  no_argument,          0, 'l'},
 | 
			
		||||
    {"description", no_argument,    0, 'd'},
 | 
			
		||||
@ -28,10 +29,32 @@ static struct option long_options[] =
 | 
			
		||||
    {"docs", no_argument,           0, 'o'},
 | 
			
		||||
    {"ttl", no_argument,            0, 'w'},
 | 
			
		||||
    {"builddate", no_argument,      0, 'b'},
 | 
			
		||||
 | 
			
		||||
    {"item", optional_argument,     0, 'i'},
 | 
			
		||||
    {"author", no_argument,         0, 'a'},
 | 
			
		||||
    {"category", no_argument,       0, 'z'},
 | 
			
		||||
    {"comments", no_argument,       0, 'f'},
 | 
			
		||||
    {"guid", no_argument,           0, 'j'},
 | 
			
		||||
    {"source", no_argument,         0, 's'},
 | 
			
		||||
 | 
			
		||||
    {"help", no_argument,           0, 'h'},
 | 
			
		||||
    {0, 0, 0, 0},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct item_flags {
 | 
			
		||||
    unsigned int title : 1;
 | 
			
		||||
    unsigned int link : 1;
 | 
			
		||||
    unsigned int description : 1;
 | 
			
		||||
    unsigned int author : 1;
 | 
			
		||||
    unsigned int category : 1;
 | 
			
		||||
    unsigned int comments : 1;
 | 
			
		||||
    unsigned int guid : 1;
 | 
			
		||||
    unsigned int pubdate : 1;
 | 
			
		||||
    unsigned int source : 1;
 | 
			
		||||
 | 
			
		||||
    int index;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct option_flags {
 | 
			
		||||
    unsigned int title : 1;
 | 
			
		||||
    unsigned int link : 1;
 | 
			
		||||
@ -46,8 +69,11 @@ struct option_flags {
 | 
			
		||||
    unsigned int ttl : 1;
 | 
			
		||||
    unsigned int builddate : 1;
 | 
			
		||||
 | 
			
		||||
    item_flags* items;
 | 
			
		||||
    unsigned int item_count;
 | 
			
		||||
    std::string uri;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void help(char*);
 | 
			
		||||
option_flags* parse_options(int, char**);
 | 
			
		||||
 | 
			
		||||
@ -15,7 +15,6 @@
 | 
			
		||||
#include <map>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
#include "tylers_utils.hpp" 
 | 
			
		||||
 | 
			
		||||
#include <rapidxml/rapidxml.hpp>
 | 
			
		||||
#include <rapidxml/rapidxml_print.hpp>
 | 
			
		||||
 | 
			
		||||
@ -11,42 +11,30 @@ using namespace rss_utils;
 | 
			
		||||
std::string rss_utils::rss_to_list(const rss& rss_obj, const option_flags* flags){
 | 
			
		||||
    std::string ret;
 | 
			
		||||
 | 
			
		||||
    if(flags->title){
 | 
			
		||||
    if(flags->title)
 | 
			
		||||
        ret += rss_obj.getTitle() + "\n";
 | 
			
		||||
    }
 | 
			
		||||
    if(flags->link){
 | 
			
		||||
    if(flags->link)
 | 
			
		||||
        ret += rss_obj.getLink() + "\n";
 | 
			
		||||
    }
 | 
			
		||||
    if(flags->description){
 | 
			
		||||
    if(flags->description)
 | 
			
		||||
        ret += rss_obj.getDescription() + "\n";
 | 
			
		||||
    }
 | 
			
		||||
    if(flags->language){
 | 
			
		||||
    if(flags->language)
 | 
			
		||||
        ret += rss_obj.getLanguage() + "\n";
 | 
			
		||||
    }
 | 
			
		||||
    if(flags->webmaster){
 | 
			
		||||
    if(flags->webmaster)
 | 
			
		||||
        ret += rss_obj.getWebMaster() + "\n";
 | 
			
		||||
    }
 | 
			
		||||
    if(flags->copyright){
 | 
			
		||||
    if(flags->copyright)
 | 
			
		||||
        ret += rss_obj.getCopyright() + "\n";
 | 
			
		||||
    }
 | 
			
		||||
    if(flags->pubdate){
 | 
			
		||||
    if(flags->pubdate)
 | 
			
		||||
        ret += rss_obj.getPubDate() + "\n";
 | 
			
		||||
    }
 | 
			
		||||
    if(flags->managingeditor){
 | 
			
		||||
    if(flags->managingeditor)
 | 
			
		||||
        ret += rss_obj.getManagingEditor() + "\n";
 | 
			
		||||
    }
 | 
			
		||||
    if(flags->generator){
 | 
			
		||||
    if(flags->generator)
 | 
			
		||||
        ret += rss_obj.getGenerator() + "\n";
 | 
			
		||||
    }
 | 
			
		||||
    if(flags->docs){
 | 
			
		||||
    if(flags->docs)
 | 
			
		||||
        ret += rss_obj.getDocs() + "\n";
 | 
			
		||||
    }
 | 
			
		||||
    if(flags->ttl){
 | 
			
		||||
    if(flags->ttl)
 | 
			
		||||
        ret += rss_obj.getTTL() + "\n";
 | 
			
		||||
    }
 | 
			
		||||
    if(flags->builddate){
 | 
			
		||||
    if(flags->builddate)
 | 
			
		||||
        ret += rss_obj.getLastBuildDate() + "\n";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(ret.length() > 0)
 | 
			
		||||
        ret.pop_back();
 | 
			
		||||
@ -55,3 +43,42 @@ std::string rss_utils::rss_to_list(const rss& rss_obj, const option_flags* flags
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string rss_utils::rss_to_items(const rss& rss_obj, const option_flags* flags){
 | 
			
		||||
    item_flags* items = flags->items;
 | 
			
		||||
    int maxItem = rss_obj.getItemCount();
 | 
			
		||||
    std::string ret;
 | 
			
		||||
 | 
			
		||||
    for(unsigned int i=0; i < flags->item_count; ++i, ++items){
 | 
			
		||||
        //if has a valid index
 | 
			
		||||
        if(items->index >= 0 && items->index < maxItem){
 | 
			
		||||
            rss_utils::item cur_item = rss_obj[items->index];
 | 
			
		||||
            if(items->title)
 | 
			
		||||
                ret += cur_item.getTitle() + "\n";
 | 
			
		||||
            if(items->link)
 | 
			
		||||
                ret += cur_item.getLink() + "\n";
 | 
			
		||||
            if(items->description)
 | 
			
		||||
                ret += cur_item.getDescription() + "\n";
 | 
			
		||||
            if(items->author)
 | 
			
		||||
                ret += cur_item.getAuthor() + "\n";
 | 
			
		||||
            if(items->category)
 | 
			
		||||
                ret += cur_item.getCategory() + "\n";
 | 
			
		||||
            if(items->comments)
 | 
			
		||||
                ret += cur_item.getComments() + "\n";
 | 
			
		||||
            if(items->guid)
 | 
			
		||||
                ret += cur_item.getGuid() + "\n";
 | 
			
		||||
            if(items->pubdate)
 | 
			
		||||
                ret += cur_item.getPubDate() + "\n";
 | 
			
		||||
            if(items->source)
 | 
			
		||||
                ret += cur_item.getSource() + "\n";
 | 
			
		||||
        } else
 | 
			
		||||
            std::cerr << "Index on item " << i << " is not valid!" << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(ret.length() > 0)
 | 
			
		||||
        ret.pop_back();
 | 
			
		||||
    else
 | 
			
		||||
        ret = "<No arguments given for items>";
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -13,6 +13,6 @@
 | 
			
		||||
 | 
			
		||||
namespace rss_utils {
 | 
			
		||||
    std::string rss_to_list(const rss&, const option_flags*);
 | 
			
		||||
    //std::string rss_to_items(const rss&
 | 
			
		||||
    std::string rss_to_items(const rss&, const option_flags*);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user