This file is indexed.

/usr/share/weechat/python/gweather.py is in weechat-scripts 20140928-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
# -*- coding: utf-8 -*-
# Copyright (c) 2010 by Jani Kesänen <jani.kesanen@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

#
# Google Weather to bar item
# (This script requires WeeChat 0.3.0.)
#
# Usage: Add "gweather" to weechat.bar.status.items or other bar you like.
#        Specify city: "/set plugins.var.python.gweather.city Tokyo".
#
#        Formatting: "/set plugins.var.python.gweather.format %C: %D°%U, %O".
#            Where: %C - city
#                   %D - temperature degrees
#                   %U - temperature unit
#                   %O - current condition
#
# History:
# 2011-03-11, Sebastien Helleu <flashcode@flashtux.org>:
#   version 0.4: get python 2.x binary for hook_process (fix problem when
#                python 3.x is default python version)
# 2010-04-15, jkesanen <jani.kesanen@gmail.com>
#   version 0.3: - added output formatting
#                - removed output and city color related options
# 2010-04-09, jkesanen <jani.kesanen@gmail.com>
#   version 0.2.1: - added support for different languages
# 2010-04-07, jkesanen <jani.kesanen@gmail.com>
#   version 0.2: - fetch weather using non-blocking hook_process interface
# 2010-04-06, jkesanen <jani.kesanen@gmail.com>
#   version 0.1: - initial release.
#

import weechat

from urllib import quote
from xml.dom import minidom
from time import time
from sys import version_info

SCRIPT_NAME    = "gweather"
SCRIPT_AUTHOR  = "Jani Kesänen <jani.kesanen@gmail.com>"
SCRIPT_VERSION = "0.4"
SCRIPT_LICENSE = "GPL3"
SCRIPT_DESC    = "Bar item with current Google weather"

# Script options
settings = {
    # City to monitor (ex. "Tokyo", "Austin, Texas", ...)
    'city'           : '',
    # Language of the conditions (ex. en, ja, fi, fr, ...)
    'language'       : 'en',
    # Temperature units (C or F)
    'unit'           : 'C',
    # Update interval in minutes
    'interval'       : '10',
    # Timeout in seconds for fetching weather data
    'timeout'        : '10',
    # The color of the output
    'output_color'   : 'white',
    # Formatting (%C = city, %D = degrees, %U = unit, %O = condition)
    'format'         : '%C: %D%U, %O',
}

# Timestamp for the last update
last_run = 0

# The last city, language and format for the need of refresh
last_city = ''
last_lang = ''
last_format = ''

# Cached copy of the last successful output
gweather_output = 'WAIT'

gweather_hook_process = ''
gweather_stdout = ''

# The url to Google's "unofficial" weather API
GOOGLE_WEATHER_URL = 'http://www.google.com/ig/api?weather=%s&hl=%s'

def parse_google_weather(xml_response):
    '''
    Parses weather report from Google

    This uses code from python-weather-api 0.2.2 by Eugene Kaznacheev <qetzal@gmail.com>.

    Returns:
      weather_data: a dictionary of weather data that exists in XML feed.
    '''
    try:
        dom = minidom.parseString(xml_response)
        weather_data = {}
        weather_dom = dom.getElementsByTagName('weather')[0]
    except:
        return

    data_structure = {
        'forecast_information': ('city', 'postal_code', 'latitude_e6', 'longitude_e6', 'forecast_date', 'current_date_time', 'unit_system'),
        'current_conditions': ('condition','temp_f', 'temp_c', 'humidity', 'wind_condition', 'icon')
    }

    for (tag, list_of_tags2) in data_structure.iteritems():
        tmp_conditions = {}
        for tag2 in list_of_tags2:
            try:
                tmp_conditions[tag2] = weather_dom.getElementsByTagName(tag)[0].getElementsByTagName(tag2)[0].getAttribute('data').strip()
            except IndexError:
                pass
        weather_data[tag] = tmp_conditions

    dom.unlink()

    return weather_data


def format_weather(weather_data):
    '''
    Formats the weather data dictionary received from Google

    Returns:
      output: a string of formatted weather data.
    '''
    output = weechat.color(weechat.config_get_plugin('output_color')) + weechat.config_get_plugin('format')
    output = output.replace('%C', weechat.config_get_plugin('city'))

    temp = 'N/A'
    condition = 'N/A'

    if weather_data:
        if len(weather_data['current_conditions']):
            if weechat.config_get_plugin('unit') == 'F':
                temp = weather_data['current_conditions']['temp_f'].encode('utf-8')
            else:
                temp = weather_data['current_conditions']['temp_c'].encode('utf-8')

            if weather_data['current_conditions'].has_key('condition'):
                condition = weather_data['current_conditions']['condition'].encode('utf-8')

    output = output.replace('%D', temp)
    output = output.replace('%O', condition)
    output = output.replace('%U', weechat.config_get_plugin('unit'))

    output += weechat.color('reset')

    return output


def gweather_data_cb(data, command, rc, stdout, stderr):
    '''
    Callback for the data fetching process.
    '''
    global last_city, last_lang, last_run, last_format
    global gweather_hook_process, gweather_stdout, gweather_output

    if rc == weechat.WEECHAT_HOOK_PROCESS_ERROR or stderr != '':
        weechat.prnt('', '%sgweather: Weather information fetching failed: %s' % (\
            weechat.prefix("error"), stderr))
        return weechat.WEECHAT_RC_ERROR

    if stdout:
        gweather_stdout += stdout

    if int(rc) < 0:
        # Process not ready
        return weechat.WEECHAT_RC_OK

    # Update status variables for succesful run
    last_run = time()
    last_city = weechat.config_get_plugin('city')
    last_lang = weechat.config_get_plugin('language')
    last_format = weechat.config_get_plugin('format')
    gweather_hook_process = ''

    if not gweather_stdout:
        return weechat.WEECHAT_RC_OK

    try:
        # The first row should contain "content-type" from HTTP header
        content_type, xml_response = gweather_stdout.split('\n', 1)
    except:
        # Failed to split received data in two at carridge return
        weechat.prnt('', '%sgweather: Invalid data received' % (weechat.prefix("error")))
        gweather_stdout = ''
        return weechat.WEECHAT_RC_ERROR

    gweather_stdout = ''

    # Determine the used character set in the response
    try:
        charset = content_type.split('charset=')[1]
    except:
        charset = 'utf-8'

    if charset.lower() != 'utf-8':
        xml_response = xml_response.decode(charset).encode('utf-8')

    # Feed the respose to parser and parsed data to formatting
    weather_data = parse_google_weather(xml_response)
    gweather_output = format_weather(weather_data)

    # Request bar item to update to the latest "gweather_output" 
    weechat.bar_item_update('gweather')

    return weechat.WEECHAT_RC_OK


def gweather_cb(*kwargs):
    ''' Callback for the Google weather bar item. '''
    global last_run, last_city, last_lang, last_format
    global gweather_output, gweather_hook_process

    # Nag if user has not specified the city
    if not weechat.config_get_plugin('city'):
        return 'SET CITY'

    # Nag if user has not specified the language
    if not weechat.config_get_plugin('language'):
        return 'SET LANGUAGE'

    # Use cached copy if it is updated recently enough
    if weechat.config_get_plugin('city') == last_city and \
       weechat.config_get_plugin('language') == last_lang and \
       weechat.config_get_plugin('format') == last_format and \
       (time() - last_run) < (int(weechat.config_get_plugin('interval')) * 60):
        return gweather_output

    location_id, hl = map(quote, (weechat.config_get_plugin('city'), \
                                  weechat.config_get_plugin('language')))
    url = GOOGLE_WEATHER_URL % (location_id, hl)

    command = 'urllib2.urlopen(\'%s\')' % (url)

    if gweather_hook_process != "":
        weechat.unhook(gweather_hook_process)
        gweather_hook_process = ''

    # Fire up the weather informationg fetching
    python2_bin = weechat.info_get("python2_bin", "") or "python"
    gweather_hook_process = weechat.hook_process(\
        python2_bin + " -c \"import urllib2;\
                     handler = " + command + ";\
                     print handler.info().dict['content-type'];\
                     print handler.read();\
                     handler.close();\"",
        int(weechat.config_get_plugin('timeout')) * 1000, "gweather_data_cb", "")

    # The old cached string is returned here. gweather_data_cb() will 
    # request a new update after the data is fetched and parsed.
    return gweather_output


def gweather_update(*kwargs):
    weechat.bar_item_update('gweather')

    return weechat.WEECHAT_RC_OK


if weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE,
        SCRIPT_DESC, '', ''):
    for option, default_value in settings.iteritems():
        if not weechat.config_is_set_plugin(option):
            weechat.config_set_plugin(option, default_value)

    weechat.bar_item_new('gweather', 'gweather_cb', '')
    weechat.bar_item_update('gweather')
    weechat.hook_timer(int(weechat.config_get_plugin('interval')) * 1000 * 60,
            0, 0, 'gweather_update', '')