1# $Revision: 1.2 $
2# $Id: Article.pm,v 1.2 2002/07/22 08:35:43 afoxson Exp $
3
4# Mail::Freshmeat::Article - parses articles from freshmeat daily newsletters
5# Copyright (c) 2002 Adam J. Foxson. All rights reserved.
6
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16
17package Mail::Freshmeat::Article;
18
19use strict;
20use 5.005;
21use Carp;
22use vars qw($VERSION $AUTOLOAD);
23use Mail::Freshmeat::Utils;
24
25local $^W;
26
27($VERSION) = '$Revision: 1.2 $' =~ /\s+(\d+\.\d+)\s+/;
28
29sub new
30{
31	my $type  = shift;
32	my $entry = shift or croak "I need to be passed an entry.";
33	my $count = shift or croak "I need to be passed a count.";
34	my $class = ref($type) || $type;
35	my $self  = bless {}, $class;
36
37	$self->{_attrs} =
38	[
39		qw
40		(
41			_title _posted_by_name _posted_by_url _posted_on _section
42			_description _url
43		)
44	];
45
46	# these are the allowed entry accessors
47	$self->{_is_attr} = {map {$_ => 1} @{$self->{_attrs}}, '_full'};
48	$self->_parse($entry, $count);
49
50	return $self;
51}
52
53sub article_keys
54{
55	my $self = shift;
56	wantarray ? @{$self->{_attrs}} : $self->{_attrs};
57}
58
59sub _parse
60{
61	my $self  = shift;
62	my $entry = shift or croak "I need to be passed an entry.";
63	my $count = shift or croak "I need to be passed a count.";
64	my @entries;
65
66	if ($entry =~
67	m/
68		^ \s* (.*) $ \n
69		^ \s* by \s (.*) \s \((.*)\) $ \n
70		^ \s* Section: \s (.*) $ \n
71		^ \s* (.*) $ \n
72		$_blank_line
73		(?s: (.+?) \n )
74		$_blank_line
75		^ \s* URL:\s (.*) $
76	/mx)
77	{
78		$self->{_title}          = $1;
79		$self->{_posted_by_name} = $2;
80		$self->{_posted_by_url}  = $3;
81		$self->{_section}        = $4;
82		$self->{_posted_on}      = $5;
83		$self->{_description}    = $6;
84		$self->{_url}            = $7;
85		$self->{_full}           = $entry;
86	}
87	else
88	{
89		_fatal_bug("Couldn't parse article $count (articles).");
90	}
91
92	for my $key (keys %$self)
93	{
94		$self->{$key} = '' if not defined $self->{$key};
95	}
96
97	return $self;
98}
99
100sub AUTOLOAD
101{
102	my $self = $_[0];
103	my ($package, $method) = ($AUTOLOAD =~ /(.*)::(.*)/);
104
105	return if $method =~ /^DESTROY$/;
106	unless ($self->{_is_attr}->{"_$method"})
107	{
108		croak "No such article accessor entry: $method; aborting";
109	}
110
111	my $code = q
112	{
113		sub
114		{
115			my $self = shift;
116			return $self->{_METHOD};
117		}
118	};
119
120	$code =~ s/METHOD/$method/g;
121
122	{
123		no strict 'refs';
124		*$AUTOLOAD = eval $code;
125	}
126
127	goto &$AUTOLOAD;
128}
129
1301;
131