summaryrefslogtreecommitdiffstats
path: root/last_shout.py
blob: 31df9c8299f130059619ea7fe007614bee4f1ebe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-

'''Post weekly Last.fm top artist to Twitter'''

__author__ = 'bdpepple@google.com'

import ConfigParser
import getopt
import os
import sys
import pylast
import twitter

USAGE = '''Usage: last_shout.py [options]
  This script posts users Top Artist from Last.fm to Twitter.
  Options:
    -h --help : print this help
    -u --user : last.fm username
    -n --number : number of last.fm top artists (default is 3)
    --consumer-key : the twitter consumer key
    --consumer-secret : the twitter consumer secret
    --access-key : the twitter access token key
    --access-secret : the twitter access token secret
    --last-access-key : the last.fm api key
    --encoding : the character set encoding used in input strings, e.g. "utf-8". [optional]

  Documentation:
  If either of the command line flags are not present, the environment
  variables TWEETUSERNAME and TWEETPASSWORD will then be checked for your
  consumer_key or consumer_secret, respectively.

  If neither the command line flags nor the environment variables are
  present, the .tweetrc file, if it exists, can be used to set the
  default consumer_key and consumer_secret.  The file should contain the
  following three lines, replacing *consumer_key* with your consumer key, and
  *consumer_secret* with your consumer secret:

  A skeletal .tweetrc file:
    [Tweet]
    consumer_key: *consumer_key*
    consumer_secret: *consumer_password*
    access_key: *access_key*
    access_secret: *access_password*

    last_access_key: *lastfm_api_key*
    last_user: *lastfm username*
'''

def PrintUsageAndExit():
    print USAGE
    sys.exit(2)

def GetConsumerKeyEnv():
    return os.environ.get("TWEETUSERNAME", None)

def GetConsumerSecretEnv():
    return os.environ.get("TWEETPASSWORD", None)

def GetAccessKeyEnv():
    return os.environ.get("TWEETACCESSKEY", None)

def GetAccessSecretEnv():
    return os.environ.get("TWEETACCESSSECRET", None)

def GetLastAccessKeyEnv():
    return os.environ.get("LASTACCESSKEY", None)

class TweetRc(object):
    def __init__(self):
        self._config = None

    def GetConsumerKey(self):
        return self._GetOption('consumer_key')

    def GetConsumerSecret(self):
        return self._GetOption('consumer_secret')

    def GetAccessKey(self):
        return self._GetOption('access_key')

    def GetAccessSecret(self):
        return self._GetOption('access_secret')

    def GetLastAccessKey(self):
        return self._GetOption('last_access_key')

    def GetLastUser(self):
        return self._GetOption('last_user')

    def _GetOption(self, option):
        try:
            return self._GetConfig().get('Tweet', option)
        except:
            return None

    def _GetConfig(self):
        if not self._config:
            self._config = ConfigParser.ConfigParser()
            self._config.read(os.path.expanduser('~/.tweetrc'))
        return self._config

def truncate_tweet(s, min_pos=0, max_pos=134, ellipsis=True):
    NOT_FOUND = -1
    ERR_MAXMIN = 'Minimum position cannot be greater than maximum position'

    if max_pos < min_pos:
        raise ValueError(ERR_MAXMIN)

    if ellipsis:
        suffix = '...'
    else:
        suffix = ''

    length = len(s)
    if length <= max_pos:
        return s + suffix
    else:
        try:
            # Return it to nearest comma if possible
            end = s.rindex(',',min_pos,max_pos)
        except ValueError:
            # Return string to nearest space
            end = s.rfind(' ',min_pos,max_pos)
            if end == NOT_FOUND:
                end = max_pos
        return s[0:end] + suffix

def build_string(list):
    
    c = len(list)
    txt = u"\u266A" + " My Top " + str(c) + " #lastfm artists: "
    x = 1
    for i in list:
        txt = txt + i.item.name + " (" + i.weight + ")"
        if x < c - 1:
            txt = txt + ", "
            x += 1
        elif x == c - 1:
            txt = txt + " & "
            x += 1
    txt = truncate_tweet(txt, ellipsis=False)
    txt = txt + " #music"
    
    return txt

def get_top_artist(last_access_key, username, number):

    network = pylast.LastFMNetwork(last_access_key)
    user = network.get_user(username)
    artist = user.get_top_artists(period="7day", limit=number)

    return artist

def send_tweet(consumer_key, consumer_secret,
               access_key, access_secret,
               txt, encoding):
    
    api = twitter.Api(consumer_key = consumer_key,
                      consumer_secret = consumer_secret,
                      access_token_key = access_key,
                      access_token_secret = access_secret,
                      input_encoding=encoding)

    try:
        status = api.PostUpdate(txt)
    except UnicodeDecodeError:
        print "Your message could not be encoded. "
        print "Perhaps it contains non-ASCII characters? "
        print "Try explicitly specifying the encoding with the --encoding flag"
        sys.exit(2)
    print "%s just posted: %s" % (status.user.name, status.text)

def main():
    try:
        longflags = ['help', 'user=', 'number=', 'consumer-key=',
                     'consumer-secret=', 'access-key=', 'access-secret=',
                     'last-access-key', 'encoding=']
        opts, args = getopt.gnu_getopt(sys.argv[1:], "hu:n:", longflags)
    except getopt.GetoptError:
        PrintUsageAndExit()
    consumer_keyflag = None
    consumer_secretflag = None
    access_keyflag = None
    access_secretflag = None
    last_access_keyflag = None
    username = None
    number = 3
    encoding = None
    for o, a in opts:
        if o in ("-h", "--help"):
            PrintUsageAndExit()
        if o in ("-u", "--user"):
            username = a
        if o in ("-n", "--number"):
            number = a
        if o in ("--consumer-key"):
            consumer_keyflag = a
        if o in ("--consumer-secret"):
            consumer_secretflag = a
        if o in ("--access-key"):
            access_keyflag = a
        if o in ("--access-secret"):
            access_secretflag = a
        if o in ("--last-access-key"):
            last_access_keyflag = a
        if o in ("--encoding"):
            encoding = a
    rc = TweetRc()
    consumer_key = consumer_keyflag or GetConsumerKeyEnv() or rc.GetConsumerKey()
    consumer_secret = consumer_secretflag or GetConsumerSecretEnv() or rc.GetConsumerSecret()
    access_key = access_keyflag or GetAccessKeyEnv() or rc.GetAccessKey()
    access_secret = access_secretflag or GetAccessSecretEnv() or rc.GetAccessSecret()
    last_access_key = last_access_keyflag or GetLastAccessKeyEnv() or rc.GetLastAccessKey()
    last_user = username or rc.GetLastUser()
    if (not consumer_key or not consumer_secret or not access_key
        or not access_secret or not last_access_key or not last_user):
        PrintUsageAndExit()
    artist = get_top_artist(last_access_key, last_user, number)
    txt = build_string(artist)
    send_tweet(consumer_key, consumer_secret,
               access_key, access_secret,
               txt, encoding)

if __name__ == "__main__":
    main()