Fortune cookies on Twitter (part 2)

A couple of day ago I posted an article Unix fortune cookies on twitter containing the source code for a Python script allowing you to post Unix type fortune cookies to your Twitter account.

In that code, I was using a package called fortune developed by Brian M. Clapper. The problem is that this package does not allow you to use the existing fortunes files provided by your operating system. The .dat file used by that package are not compatible with the .dat file of your operating system. Also the actual version of the package contains a bug and the creation of the .dat file doesn't work. That's why I developed the following get_fortune() function, which can use the operating system's fortunes files.

If you want to create your own fortune file you just need to update or create the .dat file using the standard command strfile <fortunesfile>. The default separator between each fortune is the character '%'.


Example for the creation of a new fortune file

$ vi myfortunes
When things are going well, someone will inevitably
experiment detrimentally.
%
If not controlled, work will flow to the competent
man until he submerges.

$ vi myfortunes
When things are going well, someone will inevitably
experiment detrimentally.
%
If not controlled, work will flow to the competent
man until he submerges.
$ strfile myfortunes
"myfortunes.dat" created
There were 2 strings
Longest string: 78 bytes
Shortest string: 76 bytes
$

$ strfile myfortunes
"myfortunes.dat" created
There were 2 strings
Longest string: 78 bytes
Shortest string: 76 bytes
$


The new version of twfortune uses the following function. twfortune can be downloaded from twfortune.tar.gz

Source code for get_fortune()

# fortune.py -- chooses a random fortune, as the fortune(8) program in
#               the BSD-games package does

import struct, random

def get_fortune(filename):
    """Select a random quotation
    read the .dat file, select a random quote

    Here is the c structure found in NetBSD packages describing
    the .dat file.

    typedef struct {			/* information table */
    #define	VERSION		1
        u_int32_t	str_version;	/* version number */
        u_int32_t	str_numstr;	/* # of strings in the file */
        u_int32_t	str_longlen;	/* length of longest string */
        u_int32_t	str_shortlen;	/* length of shortest string */
    #define	STR_RANDOM	0x1	/* randomized pointers */
    #define	STR_ORDERED	0x2	/* ordered pointers */
    #define	STR_ROTATED	0x4	/* rot-13'd text */
        u_int32_t	str_flags;	/* bit field for flags */
        unsigned char	stuff[4];	/* long aligned space */
    #define	str_delim	stuff[0]/* delimiting character */
    } STRFILE;

    This structure is written at the begenning of the .dat and follows
    the list of offset positions for each new string.

    """

    # On all OSs that I use, the type off_t is a long long.
    # Some OSs use a long for off_t. You should change OFFT_SIZE to reflect
    # the size of the file offsets used by your operating system.
    # The struct elemnts should be changed from q to L.
    OFFT_SIZE = struct.calcsize('q')

    datfile = open(filename+'.dat', 'r')
    # strfile structure description (5 long, followed by 4 chars)
    strfile_desc = '!5l4s'
    # read the structur length at the begining of the file
    data = datfile.read(struct.calcsize(strfile_desc))
    version, numstr, longlen, shortlen, flags, stuff = \
             struct.unpack(strfile_desc, data)
    delimiter = stuff[0]

    # pick a random number and seek to the choosen pointer.
    r = random.randint(0, numstr)
    datfile.seek(OFFT_SIZE * r, 1)
    data = datfile.read(OFFT_SIZE * 2)
    
    start, end = struct.unpack('!qq', data)
    datfile.close()

    file = open(filename, 'r')
    file.seek(start)
    fortune = file.read(end-start)
    file.close()

    # cleanup the end of the fortune 
    lines = fortune.split('\n')
    while lines[-1].strip() == delimiter or lines[-1].strip() == "": 
	lines=lines[:-1]

    return '\n'.join(lines)

if __name__ == '__main__':
    import sys, os.path
    if len(sys.argv) == 1:
	print 'Usage: %s <filename>' % os.path.basename(__file__)
	sys.exit()
    print get_fortune(sys.argv[1])

# fortune.py -- chooses a random fortune, as the fortune(8) program in
# the BSD-games package does

import struct, random

def get_fortune(filename):
"""Select a random quotation
read the .dat file, select a random quote

Here is the c structure found in NetBSD packages describing
the .dat file.

typedef struct { /* information table */
#define VERSION 1
u_int32_t str_version; /* version number */
u_int32_t str_numstr; /* # of strings in the file */
u_int32_t str_longlen; /* length of longest string */
u_int32_t str_shortlen; /* length of shortest string */
#define STR_RANDOM 0x1 /* randomized pointers */
#define STR_ORDERED 0x2 /* ordered pointers */
#define STR_ROTATED 0x4 /* rot-13'd text */
u_int32_t str_flags; /* bit field for flags */
unsigned char stuff[4]; /* long aligned space */
#define str_delim stuff[0]/* delimiting character */
} STRFILE;

This structure is written at the begenning of the .dat and follows
the list of offset positions for each new string.

"""

# On all OSs that I use, the type off_t is a long long.
# Some OSs use a long for off_t. You should change OFFT_SIZE to reflect
# the size of the file offsets used by your operating system.
# The struct elemnts should be changed from q to L.
OFFT_SIZE = struct.calcsize('q')

datfile = open(filename+'.dat', 'r')
# strfile structure description (5 long, followed by 4 chars)
strfile_desc = '!5l4s'
# read the structur length at the begining of the file
data = datfile.read(struct.calcsize(strfile_desc))
version, numstr, longlen, shortlen, flags, stuff = \
struct.unpack(strfile_desc, data)
delimiter = stuff[0]

# pick a random number and seek to the choosen pointer.
r = random.randint(0, numstr)
datfile.seek(OFFT_SIZE * r, 1)
data = datfile.read(OFFT_SIZE * 2)

start, end = struct.unpack('!qq', data)
datfile.close()

file = open(filename, 'r')
file.seek(start)
fortune = file.read(end-start)
file.close()

# cleanup the end of the fortune
lines = fortune.split('\n')
while lines[-1].strip() == delimiter or lines[-1].strip() == "":
lines=lines[:-1]

return '\n'.join(lines)

if __name__ == '__main__':
import sys, os.path
if len(sys.argv) == 1:
print 'Usage: %s <filename>' % os.path.basename(__file__)
sys.exit()
print get_fortune(sys.argv[1])
 

Comments

Posted by: sohbet Nov 21, 2009 @ 09:32

thankSsss

Posted by: chat Nov 23, 2009 @ 03:05

Actually I dont think there are many barriers to using fireox. I dont have any complaints so far its much faster than internet explorer.

Posted by: sohbet Nov 23, 2009 @ 03:05

thanks you admin eyw Kocum :)

Posted by: cheapest voip calls Nov 24, 2009 @ 20:41

Great post. It was helpful and informative. hope to see more greats posts like this one.

Posted by: free online games Nov 27, 2009 @ 00:19

Great post!

Posted by: online games Nov 27, 2009 @ 23:37

Actually I dont think there are many barriers to using fireox. I dont have any complaints so far its much faster than internet explorer.

Posted by: free insurance quotes Nov 29, 2009 @ 22:35

Thanks for sharing

Posted by: gmt master ii Dec 08, 2009 @ 00:51

Nice one! Thanks for sharing ! High quality Replica Rolex gmt master ii,welcome to choose! Thans!

Posted by: sell ugg ugg boots online ugg boots Dec 16, 2009 @ 18:40

1 Chestnut UGG Bailey Button Boots
2 Rose UGG Classic Cardy Boots 3 Sand UGG Classic Mini Boots 4 UGG Classic Argyle Knit whit 5879 5 UGG 5822 Stripe Cable Knit Chocolate White 6 Chestunt Genuine Australia classic Tall 7 Sand UGG Ultra Shotr Boots 8 Chestnut UGG Sundance Boots



Posted by: links of london Dec 20, 2009 @ 23:09

Early morning time, the mist is dim. Curved river bank, willow obviously elegant like smoke. Far does not see the mountain, nearly does not see the ship, only a little selects the lights, embellishes in the faintly recognizable mist. The young young schoolchild, sings in this mist at sunset; In a hurry the pedestrian, the moist hair clothing which fills by the mist. Most beautiful, when is in the fog the park, pavilion Taiwan pavilion, porch bridge park, fuzzy, partly visible. Let the human think that imitates, if places oneself in unreal, is considering, is in the world, plays in the heavenly palace?

Posted by: film izle Dec 23, 2009 @ 17:09

thanku so much great page.

Posted by: flowers usa Dec 27, 2009 @ 03:25

this is awesome dear!

Posted by: Rolex watches Jan 11, 2010 @ 19:01

As the business grows, replica rolex paypal has also jumped into an international brand. It is worth mentioning that, rolex replica is the ancestor of today's brand-oriented, in order to protect the quality and brand name will be printed on their products, the history of fashion in the world, is the first one first. replica watch paypal,replica watches,fake rolex.

Posted by: china wholesale Jan 14, 2010 @ 00:16

Here is the richest in the world and you can find your needs bring you harvest yes there

is no other better place than here here you are with my natural beauty but also naturally

pure green world our homes a share in the bar.God bless you! www.trademic.com

Posted by: film izle Jan 17, 2010 @ 04:57

Thanks for your good website and for sharing your experiences.

Posted by: divx film izle Jan 17, 2010 @ 04:58

Thank you for sharing your friends. Hope to see you another day.

Posted by: links of london Jan 19, 2010 @ 00:54

Here is the richest in the world and you can find your needs bring you harvest yes there

is no other better place than here here you are with my natural beauty but also naturally

pure green world our homes a share in the bar.

Posted by: partner Jan 20, 2010 @ 06:54

Your website is a big source of getting very latest information about many programs which are really very amazing for me and for everybody

Posted by: escort bayanlar Jan 20, 2010 @ 06:54

Your website is a big

Posted by: Rent a car Feb 17, 2010 @ 02:16

Your web site good.

Posted by: Oto kiralama Feb 17, 2010 @ 02:18

Early morning time, the mist is dim.

Posted by: evening dresses Feb 19, 2010 @ 06:02

I am sure a lot of people will benefit from it. Thanks!

Posted by: Nike Air Max Feb 22, 2010 @ 23:11

Very creative, one of the nicer sites I have seen today. Keep up the great work.

Posted by: Nike Air Max Mar 04, 2010 @ 00:17

So beautiful sharing!Thank you very much.

Posted by: tag heuer watch Mar 04, 2010 @ 23:30

can show a man not only his wealthy but also his high taste.tag heuer watch As the society developed, many people are pay more attention to one's wearing than before, especially a watch. tag heuer watch If you are wearing a famous brand watch, people will look up you, also will love to do business with you. You will be a successful man with a such luxury fashion watch.

Posted by: Nike Air Max Mar 11, 2010 @ 18:58

Best wishes!Your blog is very good!

Posted by: omega moon watch Mar 11, 2010 @ 20:31

I recently came across your blog and have been reading along. I thought I would leave my first comment. I don't know what to say except that I have enjoyed reading. Nice blog. I will keep visiting this blog very often.

Leave a message

(Required)
(Required and not displayed)
(Optional)
obfuscated letters Enter the text shown in the image