text 使用numpy为熊猫创建更快的滚动窗口。

使用numpy为熊猫创建更快的滚动窗口。

rolling.ipynb
{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-08-15T13:07:25.891183Z",
     "start_time": "2018-08-15T13:07:23.739938Z"
    }
   },
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This notebook shows "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-08-15T13:07:25.901159Z",
     "start_time": "2018-08-15T13:07:25.893178Z"
    }
   },
   "outputs": [],
   "source": [
    "s = pd.Series(range(10**6))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-08-15T13:07:26.046768Z",
     "start_time": "2018-08-15T13:07:25.904148Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0              NaN\n",
       "1              0.5\n",
       "2              1.5\n",
       "3              2.5\n",
       "4              3.5\n",
       "5              4.5\n",
       "6              5.5\n",
       "7              6.5\n",
       "8              7.5\n",
       "9              8.5\n",
       "10             9.5\n",
       "11            10.5\n",
       "12            11.5\n",
       "13            12.5\n",
       "14            13.5\n",
       "15            14.5\n",
       "16            15.5\n",
       "17            16.5\n",
       "18            17.5\n",
       "19            18.5\n",
       "20            19.5\n",
       "21            20.5\n",
       "22            21.5\n",
       "23            22.5\n",
       "24            23.5\n",
       "25            24.5\n",
       "26            25.5\n",
       "27            26.5\n",
       "28            27.5\n",
       "29            28.5\n",
       "            ...   \n",
       "999970    999969.5\n",
       "999971    999970.5\n",
       "999972    999971.5\n",
       "999973    999972.5\n",
       "999974    999973.5\n",
       "999975    999974.5\n",
       "999976    999975.5\n",
       "999977    999976.5\n",
       "999978    999977.5\n",
       "999979    999978.5\n",
       "999980    999979.5\n",
       "999981    999980.5\n",
       "999982    999981.5\n",
       "999983    999982.5\n",
       "999984    999983.5\n",
       "999985    999984.5\n",
       "999986    999985.5\n",
       "999987    999986.5\n",
       "999988    999987.5\n",
       "999989    999988.5\n",
       "999990    999989.5\n",
       "999991    999990.5\n",
       "999992    999991.5\n",
       "999993    999992.5\n",
       "999994    999993.5\n",
       "999995    999994.5\n",
       "999996    999995.5\n",
       "999997    999996.5\n",
       "999998    999997.5\n",
       "999999    999998.5\n",
       "Length: 1000000, dtype: float64"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s.rolling(window=2).mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-08-15T13:07:26.055744Z",
     "start_time": "2018-08-15T13:07:26.049760Z"
    }
   },
   "outputs": [],
   "source": [
    "def rolling_window(a, window):\n",
    "    shape = a.shape[:-1] + (a.shape[-1] - window + 1, window)\n",
    "    strides = a.strides + (a.strides[-1],)\n",
    "    return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-08-15T13:07:26.107613Z",
     "start_time": "2018-08-15T13:07:26.057739Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([5.000000e-01, 1.500000e+00, 2.500000e+00, ..., 9.999965e+05,\n",
       "       9.999975e+05, 9.999985e+05])"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.mean(rolling_window(s, 2), axis=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-08-15T12:59:15.696610Z",
     "start_time": "2018-08-15T12:59:15.692604Z"
    }
   },
   "source": [
    "## Performance"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-08-15T13:07:33.393120Z",
     "start_time": "2018-08-15T13:07:26.109611Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "63.7 ms ± 4.32 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n",
      "25.6 ms ± 1.34 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n"
     ]
    }
   ],
   "source": [
    "s = pd.Series(np.random.randint(10, size=10**6))\n",
    "%timeit s.rolling(window=2).mean()\n",
    "%timeit np.mean(rolling_window(s, 2), axis=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-08-15T13:07:50.905278Z",
     "start_time": "2018-08-15T13:07:33.395112Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "58.5 ms ± 1.79 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n",
      "15.4 ms ± 147 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
     ]
    }
   ],
   "source": [
    "s = pd.Series(np.random.randint(10, size=10**6))\n",
    "%timeit s.rolling(window=2).sum()\n",
    "%timeit np.sum(rolling_window(s, 2), axis=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Specializing a bit"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Using cumsum is a faster way of calculating means:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-08-15T13:07:50.912277Z",
     "start_time": "2018-08-15T13:07:50.907276Z"
    }
   },
   "outputs": [],
   "source": [
    "def moving_average(a, N) :\n",
    "    cumsum = np.cumsum(np.insert(a, 0, 0)) \n",
    "    return (cumsum[N:] - cumsum[:-N]) / float(N)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-08-15T13:08:11.026482Z",
     "start_time": "2018-08-15T13:07:50.919241Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "64.6 ms ± 3.17 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n",
      "27.2 ms ± 1.66 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n",
      "15.7 ms ± 1.11 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
     ]
    }
   ],
   "source": [
    "s = pd.Series(np.random.randint(10, size=10**6))\n",
    "%timeit s.rolling(window=2).mean()\n",
    "%timeit np.mean(rolling_window(s, 2), axis=1)\n",
    "%timeit moving_average(s.values, 2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Taking advantage of convolve in np is even faster. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-08-15T13:08:38.486719Z",
     "start_time": "2018-08-15T13:08:11.028453Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "56.8 ms ± 1.08 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n",
      "24.6 ms ± 390 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)\n",
      "14.7 ms ± 634 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n",
      "11.2 ms ± 1.42 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
     ]
    }
   ],
   "source": [
    "s = pd.Series(np.random.randint(10, size=10**6))\n",
    "%timeit s.rolling(window=2).mean()\n",
    "%timeit np.mean(rolling_window(s, 2), axis=1)\n",
    "%timeit moving_average(s.values, 2)\n",
    "%timeit np.convolve(s.values, np.ones((2,))/2, mode='valid')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finally lets look at the performance for smaller arrays. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-08-15T13:10:51.979527Z",
     "start_time": "2018-08-15T13:10:34.692373Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "242 µs ± 5.35 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n",
      "58 µs ± 1.4 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n",
      "33.9 µs ± 3.91 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n",
      "9.67 µs ± 464 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n"
     ]
    }
   ],
   "source": [
    "s = pd.Series(np.random.randint(10, size=10**3))\n",
    "%timeit s.rolling(window=2).mean()\n",
    "%timeit np.mean(rolling_window(s, 2), axis=1)\n",
    "%timeit moving_average(s.values, 2)\n",
    "%timeit np.convolve(s.values, np.ones((2,))/2, mode='valid')"
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Edit Metadata",
  "hide_input": false,
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}

text 智能手机CSS样式更新

智能手机CSS样式更新

update-body-styles-for-smartphones
/* Smartphones (portrait and landscape) ----------- */
@media only screen and(min - device - width: 320 px) and(max - device - width: 480 px) {
    body {
        font - size;
        13 px;
    }
}

/* Smartphones (landscape) ----------- */
@media only screen and(min - width: 321 px) {
    /* Styles */
    body {
        font - size;
        13 px;
    }
}

/* Smartphones (portrait) ----------- */
@media only screen and(max - width: 320 px) {
    /* Styles */
    body {
        font - size;
        13 px;
    }
}

text 刮Instagram

Scrape Instagram
function scrape_instagram( $username ) {
		$username = strtolower( $username );
		$username = str_replace( '@', '', $username );
		if ( false === ( $instagram = get_transient( 'instagram-a5-'.sanitize_title_with_dashes( $username ) ) ) ) {
			$remote = wp_remote_get( 'http://instagram.com/'.trim( $username ) );
			if ( is_wp_error( $remote ) )
				return new WP_Error( 'site_down', esc_html__( 'Unable to communicate with Instagram.', 'wp-instagram-widget' ) );
			if ( 200 != wp_remote_retrieve_response_code( $remote ) )
				return new WP_Error( 'invalid_response', esc_html__( 'Instagram did not return a 200.', 'wp-instagram-widget' ) );
			$shards = explode( 'window._sharedData = ', $remote['body'] );
			$insta_json = explode( ';</script>', $shards[1] );
			$insta_array = json_decode( $insta_json[0], TRUE );
			if ( ! $insta_array )
				return new WP_Error( 'bad_json', esc_html__( 'Instagram has returned invalid data.', 'wp-instagram-widget' ) );
			if ( isset( $insta_array['entry_data']['ProfilePage'][0]['user']['media']['nodes'] ) ) {
				$images = $insta_array['entry_data']['ProfilePage'][0]['user']['media']['nodes'];
			} else {
				return new WP_Error( 'bad_json_2', esc_html__( 'Instagram has returned invalid data.', 'wp-instagram-widget' ) );
			}
			if ( ! is_array( $images ) )
				return new WP_Error( 'bad_array', esc_html__( 'Instagram has returned invalid data.', 'wp-instagram-widget' ) );
			$instagram = array();
			foreach ( $images as $image ) {
				$image['thumbnail_src'] = preg_replace( '/^https?\:/i', '', $image['thumbnail_src'] );
				$image['display_src'] = preg_replace( '/^https?\:/i', '', $image['display_src'] );
				// handle both types of CDN url
				if ( ( strpos( $image['thumbnail_src'], 's640x640' ) !== false ) ) {
					$image['thumbnail'] = str_replace( 's640x640', 's160x160', $image['thumbnail_src'] );
					$image['small'] = str_replace( 's640x640', 's320x320', $image['thumbnail_src'] );
				} else {
					$urlparts = wp_parse_url( $image['thumbnail_src'] );
					$pathparts = explode( '/', $urlparts['path'] );
					array_splice( $pathparts, 3, 0, array( 's160x160' ) );
					$image['thumbnail'] = '//' . $urlparts['host'] . implode( '/', $pathparts );
					$pathparts[3] = 's320x320';
					$image['small'] = '//' . $urlparts['host'] . implode( '/', $pathparts );
				}
				$image['large'] = $image['thumbnail_src'];
				if ( $image['is_video'] == true ) {
					$type = 'video';
				} else {
					$type = 'image';
				}
				$caption = __( 'Instagram Image', 'wp-instagram-widget' );
				if ( ! empty( $image['caption'] ) ) {
					$caption = $image['caption'];
				}
				$instagram[] = array(
					'description'   => $caption,
					'link'		  	=> trailingslashit( '//instagram.com/p/' . $image['code'] ),
					'time'		  	=> $image['date'],
					'comments'	  	=> $image['comments']['count'],
					'likes'		 	=> $image['likes']['count'],
					'thumbnail'	 	=> $image['thumbnail'],
					'small'			=> $image['small'],
					'large'			=> $image['large'],
					'original'		=> $image['display_src'],
					'type'		  	=> $type
				);
			}
			// do not set an empty transient - should help catch private or empty accounts
			if ( ! empty( $instagram ) ) {
				$instagram = base64_encode( serialize( $instagram ) );
				set_transient( 'instagram-a5-'.sanitize_title_with_dashes( $username ), $instagram, apply_filters( 'null_instagram_cache_time', HOUR_IN_SECONDS*2 ) );
			}
		}
		if ( ! empty( $instagram ) ) {
			return unserialize( base64_decode( $instagram ) );
		} else {
			return new WP_Error( 'no_images', esc_html__( 'Instagram did not return any images.', 'wp-instagram-widget' ) );
		}
	}

text Fb Api

Fb Api
<?php 
require_once get_template_directory().'/Facebook/autoload.php';
if ( !function_exists('media_handle_upload') ) {
    require_once(ABSPATH . "wp-admin" . '/includes/image.php');
    require_once(ABSPATH . "wp-admin" . '/includes/file.php');
    require_once(ABSPATH . "wp-admin" . '/includes/media.php');
}
global $wpdb;
$current_url = home_url(add_query_arg(array(),$_SERVER['REQUEST_URI']));
if (isset($_GET['act']) && $_GET['act']=='fbapp_edit' && isset($_GET['id'])) {
    $errors = '';
    $id = $_GET['id'];
    $sql_prep = $wpdb->prepare("SELECT * FROM ".$wpdb->prefix."fbapp WHERE ID = %s", $id);
    $record = $wpdb->get_row($sql_prep, OBJECT);
    $fbapp_id = $record->fbapp_id;
    $fbapp_name = $record->fbapp_name;
    $fbapp_secret = $record->fbapp_secret;
    $fbapp_userid = $record->fbapp_userid;
    $fbapp_token = $record->fbapp_token;    
    $fbapp_pages = $record->fbapp_pages;
    $fbapp_page_crawler = $record->fbapp_page_crawler;
    $fbapp_get_type = $record->fbapp_get_type;
}
if (isset($_POST['save_record'])) {
	$fbapp_id = $_POST['fbapp_id'];
    $fbapp_name = $_POST['fbapp_name'];
	$fbapp_secret = $_POST['fbapp_secret'];
	$fbapp_userid = $_POST['fbapp_userid'];
    $fbapp_token = $_POST['fbapp_token'];
    $fbapp_pages = $_POST['fbapp_pages'];
    $fbapp_page_crawler = $_POST['fbapp_page_crawler'];
    $fbapp_get_type = $_POST['fbapp_get_type'];
	$fields = array();
	$fields['fbapp_id'] = $fbapp_id;
    $fields['fbapp_name'] = $fbapp_name;
	$fields['fbapp_secret'] = $fbapp_secret;
	$fields['fbapp_userid'] = $fbapp_userid;
    $fields['fbapp_token'] = $fbapp_token;
    $fields['fbapp_pages'] = $fbapp_pages;
    $fields['fbapp_page_crawler'] = $fbapp_page_crawler;
    $fields['fbapp_get_type'] = $fbapp_get_type;
	$where = array('ID'=>$_GET['id']);
	$updated = $wpdb->update($wpdb->prefix.'fbapp', $fields, $where);
	if($updated){
		wp_redirect(get_page_link('settings'));die;
	}
}
if(isset($_POST['fb_auth'])){
    $my_url=urlencode('http://it.thietkewebwp.info/settings/?act=fbapp_edit&id=1');
    $fbapp_session_state = md5(uniqid(rand(), TRUE));
    setcookie("fbapp_session_state",$fbapp_session_state,"0","/");
    $dialog_url = "https://www.facebook.com/".FBAP_FB_API_VERSION."/dialog/oauth?client_id="
                . $fbapp_id . "&redirect_uri=" . $my_url . "&state="
                . $fbapp_session_state . "&scope=email,public_profile,publish_pages,user_posts,publish_actions,manage_pages";
    wp_redirect($dialog_url);
    die;
}
if(isset($_COOKIE['fbapp_session_state']) && isset($_REQUEST['state']) && ($_COOKIE['fbapp_session_state'] === $_REQUEST['state'])) :    
    $my_url=urlencode('http://it.thietkewebwp.info/settings/?act=fbapp_edit&id=1');
    $code = $_REQUEST["code"];
    $token_url = "https://graph.facebook.com/".FBAP_FB_API_VERSION."/oauth/access_token?"
    . "client_id=" . $fbapp_id . "&redirect_uri=" . $my_url
    . "&client_secret=" . $fbapp_secret . "&code=" . $code;

    $params = null;$access_token="";
    $response = wp_remote_get($token_url);

    if(is_array($response))
    {
        if(isset($response['body']))
        {
            parse_str($response['body'], $params);            
            
            if(isset($params['access_token'])){$access_token = $params['access_token'];}
        }
    }
    
    if($access_token!=""){      
        $fields = array();
        $fields['fbapp_token'] = $access_token;
        $where = array('ID'=>$_GET['id']);
    
        $updated = $wpdb->update($wpdb->prefix.'fbapp', $fields, $where);
        // if($updated){
        //     wp_redirect(get_page_link('settings'));die;
        // }
    }
endif;

if(isset($_POST['pubthoi']) && !empty($_POST['postLink_link'])){
	// wp_delete_post(304);
	$fbapp_page = explode('-',$fbapp_pages);	
	$fb = new Facebook\Facebook([
	    'app_id' => $fbapp_id,
	    'app_secret' => $fbapp_secret,
	    'default_graph_version' => 'v2.4',
	    'default_access_token' => isset($fbapp_page[1]) ? $fbapp_page[1] : '1044300938965725|ca1da3267aca55b7b6c00494e9ac19c6'
	]);
	// echo '<pre>';
	// var_dump($_POST);
	// echo '</pre>';
	// die;
	$linkData = [
		'link' => $_POST['postLink_link'],		
		'message' => !empty($_POST['postLink_message']) ? $_POST['postLink_message'] : '',
		'name' => !empty($_POST['postLink_name']) ? $_POST['postLink_name'] : '',
		'caption' => !empty($_POST['postLink_caption']) ? $_POST['postLink_caption'] : "yan.vn | Bởi YAN News",
		'description' => !empty($_POST['postLink_description']) ? $_POST['postLink_description'] : '',
		'picture' => !empty($_POST['postLink_picture']) ? $_POST['postLink_picture'] : '',	
        // 'with_tags'=>'https://www.facebook.com/tuoitre.newspaper',
	];
	try {
   		$response = $fb->post('/'.$fbapp_page[0].'/feed', $linkData,$fbapp_page[1]);
	}catch (Facebook\Exceptions\FacebookResponseException $e) {
   	// When Graph returns an error
   		echo 'Graph returned an error: ' . $e->getMessage();
   		exit;
	}catch (Facebook\Exceptions\FacebookSDKException $e) {
   		// When validation fails or other local issues
   		echo 'Facebook SDK returned an error: ' . $e->getMessage();
   		exit;
	}
}

?>
<form method='POST' action='' class="settings">
    <div class="row">
        <div class="col-sm-6">
            <div class="panel panel-default">
                <div class="panel-heading">
                    <h3 class="panel-title">Facebook Settings</h3>
                </div>
                <div class="panel-body">
                	<div class="form-group">
	                    <label for="">Fanpage</label>
	                    <input type="text" name="fbapp_name" class="form-control" placeholder="Facebook Fanpage" value="<?php echo $fbapp_name; ?>">
	                </div>
	                <div class="form-group">
	                    <label for="fbapp_id">Application id</label>
	                    <input type="text" name="fbapp_id" class="form-control" id="fbapp_id" placeholder="Facebook app ID" value="<?php echo $fbapp_id; ?>" />
	                </div>
	                <div class="form-group">
	                    <label for="fbapp_secret">Application secret</label>
	                    <input type="text" name="fbapp_secret" class="form-control" id="fbapp_secret" placeholder="Facebook app Secret" value="<?php echo $fbapp_secret; ?>"/>
	                </div>
	                <div class="form-group">
	                    <label for="fbapp_user">Facebook user id</label>
	                    <input type="text" name="fbapp_userid" class="form-control" id="fbapp_userid" placeholder="Facebook user id" value="<?php echo $fbapp_userid; ?>"/>
	               	</div>
                </div>
            </div>
        </div><!-- /.col-sm-6 -->
        <div class="col-sm-6">
        	<div class="panel panel-default">
                <div class="panel-heading">
                    <h3 class="panel-title">Facebook Settings</h3>
                </div>
                <div class="panel-body">
                	<div class="form-group">
	                    <input type="submit" class="submit_fbap_new" name="fb_auth" value="Reauthorize" title="Reauthorize the account">
	                    <textarea class="form-control" name="fbapp_token" id="code_access" cols="30" rows="4"><?php echo $fbapp_token; ?></textarea>
	                </div>
                   	<div class="form-group">
                    <?php if(!empty($fbapp_token)): 
                        echo '<label for="">Select facebook pages</label>';
                        $offset = 0;
                        $limit = 100;
                        $data = array();
                        do {
                            $result1 = "";
                            $pagearray1 = "";
                            $pp = wp_remote_get("https://graph.facebook.com/" . FBAP_FB_API_VERSION . "/me/accounts?access_token=$fbapp_token&limit=$limit&offset=$offset");                      
                            if (is_array($pp)) {
                                $result1 = $pp['body'];
                                $pagearray1 = json_decode($result1);
                                if (is_array($pagearray1->data))
                                    $data = array_merge($data, $pagearray1->data);
                            } else
                                break;
                            $offset += $limit;
                        }while (isset($pagearray1->paging->next));
                        $count = count($data);
                        $fbap_pages_ids0 = array();
                        if ($fbapp_pages != "") $fbap_pages_ids0 = explode(",", $fbapp_pages);
                        $fbap_pages_ids = array();
                        for ($i = 0; $i < count($fbap_pages_ids0); $i++) {
                            if ($fbap_pages_ids0[$i] != "-1")
                                $fbap_pages_ids[$i] = trim(substr($fbap_pages_ids0[$i], 0, strpos($fbap_pages_ids0[$i], "-")));
                            else
                                $fbap_pages_ids[$i] = $fbap_pages_ids0[$i];
                        }
                        ?>
                        <select class="form-control" name="fbapp_pages">
                            <option value="-1" <?php if (in_array(-1, $fbap_pages_ids)) echo "selected" ?>>Profile Page</option>
                            <?php for ($i = 0; $i < $count; $i++): ?>
                            <option value="<?php echo $data[$i]->id . "-" . $data[$i]->access_token; ?>" <?php if (in_array($data[$i]->id, $fbap_pages_ids)) echo "selected" ?>><?php echo $data[$i]->name; ?></option>
                            <?php endfor; ?>
                        </select>
                        <?php endif; ?>
                    </div>
                    <div class="form-group">
	                    <label for="fbapp_page_crawler">Page Get Data</label>
	                    <input type="text" name="fbapp_page_crawler" class="form-control" id="fbapp_page_crawler" placeholder="Facebook Fanpage Crawler" value="<?php echo $fbapp_page_crawler; ?>" />
	                </div>
                    <label for="">Loại tin cần lấy</label>
                    <div class="form-group">
                    	<label class="checkbox-inline">
                    		<input <?php if($fbapp_get_type=='all') echo 'checked=checked'; ?> type="checkbox" name="fbapp_get_type" value="all"> Tất cả
                    	</label>
                    	<label class="checkbox-inline">
                    		<input <?php if($fbapp_get_type=='video') echo 'checked=checked'; ?> type="checkbox" name="fbapp_get_type" value="video"> Video
                    	</label>
                    	<label class="checkbox-inline">
                    		<input <?php if($fbapp_get_type=='photo') echo 'checked=checked'; ?> type="checkbox" name="fbapp_get_type" value="photo"> Photo
                    	</label>
                    	<label class="checkbox-inline">
                    		<input <?php if($fbapp_get_type=='status') echo 'checked=checked'; ?> type="checkbox" name="fbapp_get_type" value="status"> Status
                    	</label>
                    	<label class="checkbox-inline">
                    		<input <?php if($fbapp_get_type=='link') echo 'checked=checked'; ?> type="checkbox" name="fbapp_get_type" value="link"> Gif
                    	</label>
                    </div>

                </div>
            </div>
            
        </div>
    </div>
    <div class="row">
	    <div class="col-sm-6">
	    	<div class="panel panel-default">
		    		<div class="panel-body">
				<input type="hidden" name="postType" id="postType" value="link">
					<div class="formField">
						<label for="message">Message <a href="#" data-toggle="tooltip" data-placement="top" style="float:right" title="" data-original-title="Spinning example : {Hello|Howdy|Hola} to you, {Mr.|Mrs.|Ms.} {foo|bar|foobar}!!"><span class="glyphicon glyphicon-question-sign"></span></a></label>
						<textarea name="message" id="message" rows="3" cols="50" class="form-control" placeholder="Your status here..."></textarea>
						
					</div>

					<div id="postLinkDetails" style="">
						<div class="formField">
							<label for="link">Link</label>
							<input type="text" name="postLink_link" id="link" class="form-control" value="" placeholder="Post link here.">
						</div>
						<div class="formField">
							<label for="picture">Picture</label>
							<input type="text" name="postLink_picture" id="picture" class="form-control" value="" placeholder="Post picture here.">
						</div>
						<div class="formField">
							<label for="name">Name</label>
							<input type="text" id="name" name="postLink_name" class="form-control" value="" placeholder="Post name here.">
						</div>
						<div class="formField">
							<label for="caption">Caption</label>
							<input type="text" name="postLink_caption" id="caption" class="form-control" value="" placeholder="Post Caption here.">
						</div>
						<div class="formField">
							<label for="description">Description</label>
							<textarea name="postLink_description" id="description" rows="3" cols="50" class="form-control" placeholder="Post description here."></textarea>
						</div>
					</div>
					<br>
					<div class="formField">
						<button type="submit" class="btn btn-primary" id="post" name="pubthoi">
							<span class="glyphicon glyphicon-send"></span> Send 
						</button>
						<span class="messageBox"></span>
					</div>
				</div>
	    	</div>
	    </div>
	</div>
    <button type="submit" name="pubthoi">Pub thoi</button>
    <button type="submit" name="submit_page">Submit</button>
    <input type="submit" name="save_record" value="Save change" class="btn btn-primary" />
</form>

text 生活在

生活在

gistfile1.txt
http://www.missiontolearn.com/2013/10/self-directed-learning-success/

1. Takes initiative
2. Is comfortable with independence
3. Is persistent
4. Accepts responsibility
5. Views problems as challenges, not obstacles
6. Is capable of self-discipline
7. Has a high degree of curiosity
8. Has a strong desire to learn or change
9. Is self-confident
10. Is able to use basic study skills
11. Organizes his or her time
12. Sets an appropriate pace for learning
13. Develops a plan for completing work
14. Has a tendency to be goal-oriented
15. Enjoys learning

text Bash档案

Bash档案

gistfile1.txt
### Aliases



# Open specified files in Sublime Text
# "s ." will open the current directory in Sublime
alias subl='open -a "Sublime Text"'
alias phpini='cd /usr/local/etc/php/7.1; subl php.ini'

# Color LS
colorflag="-G"
alias ls="command ls ${colorflag}"
alias l="ls -lF ${colorflag}" # all files, in long format
alias la="ls -laF ${colorflag}" # all files inc dotfiles, in long format
alias lsd='ls -lF ${colorflag} | grep "^d"' # only directories

# Quicker navigation
alias ..="cd .."
alias ...="cd ../.."
alias ....="cd ../../.."
alias .....="cd ../../../.."

# Shortcuts to my Code folder in my home directory
alias code="cd ~/Code"
alias sites="cd ~/Code/sites"

# Enable aliases to be sudo’ed
alias sudo='sudo '

# Colored up cat!
# You must install Pygments first - "sudo easy_install Pygments"
# alias c='pygmentize -O style=monokai -f console256 -g'


### Prompt Colors
# Modified version of @gf3’s Sexy Bash Prompt
# (https://github.com/gf3/dotfiles)
if [[ $COLORTERM = gnome-* && $TERM = xterm ]] && infocmp gnome-256color >/dev/null 2>&1; then
	export TERM=gnome-256color
elif infocmp xterm-256color >/dev/null 2>&1; then
	export TERM=xterm-256color
fi

if tput setaf 1 &> /dev/null; then
	tput sgr0
	if [[ $(tput colors) -ge 256 ]] 2>/dev/null; then
		BLACK=$(tput setaf 190)
		MAGENTA=$(tput setaf 9)
		ORANGE=$(tput setaf 172)
		GREEN=$(tput setaf 190)
		PURPLE=$(tput setaf 141)
		WHITE=$(tput setaf 0)
	else
		BLACK=$(tput setaf 190)
		MAGENTA=$(tput setaf 5)
		ORANGE=$(tput setaf 4)
		GREEN=$(tput setaf 2)
		PURPLE=$(tput setaf 1)
		WHITE=$(tput setaf 7)
	fi
	BOLD=$(tput bold)
	RESET=$(tput sgr0)
else
	BLACK="\033[01;30m"
	MAGENTA="\033[1;31m"
	ORANGE="\033[1;33m"
	GREEN="\033[1;32m"
	PURPLE="\033[1;35m"
	WHITE="\033[1;37m"
	BOLD=""
	RESET="\033[m"
fi

export BLACK
export MAGENTA
export ORANGE
export GREEN
export PURPLE
export WHITE
export BOLD
export RESET


# Change this symbol to something sweet.
# (http://en.wikipedia.org/wiki/Unicode_symbols)
symbol="◻ "


parse_git_branch() {
    git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/'
}

# PS1='\[\e[1;91m\][\u@\h \w]\[\e[0m\][\033[32m\]\$(parse_git_branch)\[\033[00m\]$'

export PS1="\[${BOLD}${MAGENTA}\]\u \[$WHITE\]in \[$GREEN\]\w\[$WHITE\]\$([[ -n \$(git branch 2> /dev/null) ]] && echo \" on \")\[$PURPLE\]\$(parse_git_branch)\[$WHITE\]\n$symbol\[$RESET\]"
export PS2="\[$ORANGE\]→ \[$RESET\]"






### Misc

# Only show the current directory's name in the tab
export PROMPT_COMMAND='echo -ne "\033]0;${PWD##*/}\007"'


#Export PATH=/Applications/MAMP/Library/bin:/Applications/MAMP/bin/php/php5.6.7/bin:$PATH

PATH=~/.composer/vendor/bin:$PATH
export PATH=$PATH:~/bin

# echo 'export PATH="$PATH:$HOME/.composer/vendor/bin"' >> ~/.bash_profile
# export PATH=$HOME/bin:/usr/local/bin:~/.composer/vendor/bin:$PATH


# echo 'export PATH="$PATH:~/.composer/vendor/bin"' >> ~/.bashrc


# Good ones to keep and use
alias show_files='defaults write com.apple.finder AppleShowAllFiles YES; killall Finder /System/Library/CoreServices/Finder.app'
alias hide_files='defaults write com.apple.finder AppleShowAllFiles NO; killall Finder /System/Library/CoreServices/Finder.app'
alias copykey='cat ~/.ssh/github_rsa.key | pbcopy'
alias c='clear'
alias art="php artisan"
alias routes="php artisan routes"
alias bashprofile='cd ~/; subl .bash_profile'

export PATH="/opt/local/bin:/opt/local/sbin:$PATH"

text 删除意外提交给git的大文件

删除意外提交给git的大文件

gistfile1.txt
git filter-branch --tree-filter 'rm -rf path/to/your/file' HEAD

text 图像刮板

Image Scraper
<?php
ini_set('display_errors', 'On');

require 'vendor/autoload.php';
use Symfony\Component\DomCrawler\Crawler;
use Symfony\Component\CssSelector\CssSelectorConverter;

$client = new GuzzleHttp\Client();
$url = 'https://us.fotolia.com/search?k=cats&filters%5Bcontent_type%3Aphoto%5D=1&search-submit=Search&limit=5';
$data = $client->get($url);
$data = $data->getbody(true);
$data = "$data";

// check to see the site is working
// print_r($data);

$images = array();
// crawl the page looking for links
$crawler = new Crawler($data);
$my_data = $crawler->filter('a.thumb-frame')->each(function (Crawler $node, $i) use($images) {
	// get the url of the single page for each image
    $value = $node->extract(array('href'));
    // setup base url
    $base_url = 'https://us.fotolia.com';
    // crawl each page
    $client = new GuzzleHttp\Client();
    $url = $base_url.$value[0];
    $data = $client->get($url);
	$data = $data->getbody(true);
	$data = "$data";

	// check to see if its getting the first one
	// print_r($data);
	// exit;

	$crawler = new Crawler($data);

	$title = $crawler->filter('h1.content-title')->text();
	$img_src = $crawler->filter('.content-detail-thumbnail img')->attr('src');
	$keywords_list = $crawler->filter('#keywords_list')->text();
	
	$image = array($title, $img_src);
	// add the image to the array of images
	$images[] = $image;
	return $images;
});
	
	// merge the arrays down
	$my_data = array_map('current', $my_data);
	// print_r($my_data);

	// write the array into a csv document

	$file = fopen("images.csv","w");
	$header = array("title","img");
	fputcsv ($file, $header, ",");
	foreach($my_data as $row){
        fputcsv($file, $row, ",");
   	}
   	fclose($file);

   	echo 'You got Images!'




?>

text Telstra诚实报告 - 监控连接丢失

Telstra诚实报告 - 监控连接丢失

telstra.js
var spawn = require('child_process').spawn;

const ADDR                    = process.env.PING_HOST || "8.8.8.8"
const THRESHOLD_FOR_REPORT_MS = process.env.THRESHOLD || 2000
const SUMMARY_LOG_FILE        = process.env.SUMMARY_LOG || `${__dirname}/telstra-summary.log`

var serviceStart    = new Date
var pingCount       = 0
var failedPingCount = 0
var downtimeCount   = 0
var totalDowntimeMs = 0
var longestOutage   = { value: 0, start: '', end: '' }
var start;

var seconds = (ms) => {
  return `${ ms / 1000 }s`
}

var mins = (ms) => {
  return `${ ms / 1000 / 60 }m`
}

var hours = (ms) => {
  return `${ ms / 1000 / 60 / 60 }h`
}

var durations = (ms) => {
  return `${ seconds(ms) } (${ mins(ms) } or ${ hours(ms) })`
}

var log = (msg) => {
  console.log.apply( console, [ (new Date).toString(), msg ] )
}

var logSummary = () => {
  var pingFailureRate = failedPingCount / pingCount * 100
  var averageDowntime = ( totalDowntimeMs / downtimeCount ) || 0

  return `
    FROM ${ serviceStart.toString() } TO ${ (new Date).toString() }:
    ===========
    Total Dropouts: ${ downtimeCount }
    Ping failure rate: ${ pingFailureRate }% (${ failedPingCount } of ${ pingCount } pings failed)
    avg downtime: ${ durations( averageDowntime ) }
    Total downtime: ${ durations( totalDowntimeMs ) }
    Longest outage:
      downtime: ${ durations( longestOutage.value ) }
      started: ${ longestOutage.start }
      ended: ${ longestOutage.end }
    ===========
  `
}

var writeLogSummary = () => {
  require('fs').writeFileSync(SUMMARY_LOG_FILE, logSummary())
}

log(`Started Connectivity Monitor - logging drops longer than ${ seconds( THRESHOLD_FOR_REPORT_MS ) }\n`)
var child = spawn("ping", [ ADDR ])


child.stdout.on('data', (data) => {
  var now = new Date

  pingCount++
  var str = data.toString()

  if( new RegExp(`.*from ${ ADDR.replace(/\./, '\.') }.+time=`).test( str ) ) {
    var downtime = now - (start || now)
    if(downtime >= THRESHOLD_FOR_REPORT_MS ) {

      if(downtime > longestOutage.value) {
        longestOutage.value = downtime
        longestOutage.start = start
        longestOutage.end   = now
      }

      totalDowntimeMs += downtime
      log(`Reconnected. Outage lasted ${ seconds( downtime ) }\n`)
      start = null
    }

    return
  }

  failedPingCount++

  if(start) return

  start = new Date();
  downtimeCount++
  log(`DISCONNECTION STARTED: ${ str.replace(/\n/g, '') }`)
});

child.stderr.on('data', (data) => { log(`Error: ${data}`) });

child.on('close', (code) => { log(`Closing ${code}`) });

[ "SIGINT", "SIGTERM" ].forEach( (signal) => {
  process.on(signal, () => {
    log( logSummary() )
    process.exit()
  })
})

process.on('SIGHUP', writeLogSummary)
telstra-summary.sh
# will signal the telstra-monitor daemon to write the summary of outages so far to the configured file
# run this as sudo if querying as a daemon
pgrep -lf telstra-monitor | awk '{print $1}' | sudo xargs kill -s HUP && cat /var/log/telstra-monitor-summary.log
telstra-monitor.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>telstra-monitor</string>

    <key>KeepAlive</key>
    <true/>

    <key>EnvironmentVariables</key>
    <dict>
        <key>THRESHOLD</key>
        <string>20000</string>

        <key>SUMMARY_LOG</key>
        <string>/var/log/telstra-monitor-summary.log</string>
    </dict>

    <key>ProgramArguments</key>
    <array>
        <string>/Users/benkitzelman/.nvm/versions/node/v8.6.0/bin/node</string>
        <string>/Users/benkitzelman/dev/projects/telstra-monitor/index.js</string>
    </array>

    <key>StandardErrorPath</key>
    <string>/var/log/telstra-monitor.err</string>

    <key>StandardOutPath</key>
    <string>/var/log/telstra-monitor.log</string>
</dict>
</plist>

text slack2html

slack2html

gistfile1.txt
<?
/////////////////////
// slack2html
// by @levelsio
/////////////////////
//
/////////////////////
// WHAT DOES THIS DO?
/////////////////////
//
// Slack lets you export the chat logs (back to the first messages!), even if
// you are a free user (and have a 10,000 user limit)
//
// This is pretty useful for big chat groups (like mine, #nomads), where you
// do wanna see the logs, but can't see them within Slack
//
// Problem is that Slack exports it as JSON files, which is a bit unusable,
// so this script makes it into actual HTML files that look like Slack chats
//
///////////////////
// INSTRUCTIONS
///////////////////
//
// Run this script inside the directory of an extracted (!) Slack export zip
// e.g. "/tmp/#nomads Slack export Aug 25 2015" like this:
// MacBook-Pro:#nomads Slack export Aug 25 2015 mbp$ php slack2html.php
//
// It will then make two dirs:
// 	/slack2html/json
// 	/slack2html/html
//
// In the JSON dir it will put each channels chat log combined from all the
// daily logs that Slack outputs (e.g. /channel/2014-11-26.json)
//
// In the HTML dir it will generate HTML files with Slack's typical styling.
// It will also create an index.html that shows all channels
// 
///////////////////
// FEEDBACK
///////////////////
//
// Let me know any bugs by tweeting me @levelsio
//
// Hope this helps!
// 
// Pieter @levelsio
//
/////////////////////

    ini_set('memory_limit', '1024M');
	date_default_timezone_set('UTC');
	mb_internal_encoding("UTF-8");
	error_reporting(E_ERROR);

	// <config>
		$stylesheet="
			* {
				font-family:sans-serif;
			}
			body {
				text-align:center;
				padding:1em;
			}
			.messages {
				width:100%;
				max-width:700px;
				text-align:left;
				display:inline-block;
			}
			.messages img {
				background-color:rgb(248,244,240);
				width:36px;
				height:36px;
				border-radius:0.2em;
				display:inline-block;
				vertical-align:top;
				margin-right:0.65em;
			}
			.messages .time {
				display:inline-block;
				color:rgb(200,200,200);
				margin-left:0.5em;
			}
			.messages .username {
				display:inline-block;
				font-weight:600;
				line-height:1;
			}
			.messages .message {
				display:inline-block;
				vertical-align:top;
				line-height:1;
				width:calc(100% - 3em);
			}
			.messages .message .msg {
				line-height:1.5;
			}
		";
	// </config>

    // <compile daily logs into single channel logs>
		$files=scandir(__DIR__);
		$baseDir=__DIR__.'/../slack2html';
		$jsonDir=$baseDir.'/'.'json';
		if(!is_dir($baseDir)) mkdir($baseDir);
		if(!is_dir($jsonDir)) mkdir($jsonDir);

		foreach($files as $channel) {
			if($channel=='.' || $channel=='..') continue;
			if(is_dir($channel)) {
				$channelJsonFile=$jsonDir.'/'.$channel.'.json';
				if(file_exists($channelJsonFile)) {
					echo "JSON already exists ".$channelJsonFile."\n";
					continue;
				}

				unset($chats);
				$chats=array();

				echo '====='."\n";
				echo 'Combining JSON files for #'.$channel."\n";
				echo '====='."\n";

				$dates=scandir(__DIR__.'/'.$channel);
				foreach($dates as $date) {
					if(!is_dir($date)) {
						echo '.';
						$messages=json_decode(file_get_contents(__DIR__.'/'.$channel.'/'.$date),true);
						if(empty($messages)) continue;
						foreach($messages as $message) {
							array_push($chats,$message);
						}
					}
				}
				echo "\n";

				file_put_contents($channelJsonFile,json_encode($chats));
				echo number_format(count($chats)).' messages exported to '.$channelJsonFile."\n";
			}
		}
    // </compile daily logs into single channel logs>

	// <load users file>
		$users=json_decode(file_get_contents(__DIR__.'/'.'users.json'),true);
		$usersById=array();
		foreach($users as $user) {
			$usersById[$user['id']]=$user;
		}
	// </load users file>

	// <load channels file>
		$channels=json_decode(file_get_contents(__DIR__.'/'.'channels.json'),true);
		$channelsById=array();
		foreach($channels as $channel) {
			$channelsById[$channel['id']]=$channel;
		}
	// </load channels file>

	// <generate html from channel logs>
		$htmlDir=$baseDir.'/'.'html';
		if(!is_dir($htmlDir)) mkdir($htmlDir);
		$channels=scandir($jsonDir);
		$channelNames=array();
		$mostRecentChannelTimestamps=array();
		foreach($channels as $channel) {
			if($channel=='.' || $channel=='..') continue;
			if(is_dir($channel)) continue;

			$mostRecentChannelTimestamp=0;
			if($message['ts']>$mostRecentChannelTimestamp) {
				$mostRecentChannelTimestamp=$message['ts'];
			}
			$array=explode('.json',$channel);
			$channelName=$array[0];
			
			$channelHtmlFile=$htmlDir.'/'.$channelName.'.html';
			if(file_exists($channelHtmlFile)) {
				echo "HTML already exists ".$channelJsonFile."\n";
				continue;
			}

			array_push($channelNames,$channelName);
			echo '====='."\n";
			echo 'Generating HTML for #'.$channelName."\n";
			echo '====='."\n";
			$messages=json_decode(file_get_contents($jsonDir.'/'.$channel),true);
			if(empty($messages)) continue;
			$htmlMessages='<html><body><style>'.$stylesheet.'</style><div class="messages">';
			foreach($messages as $message) {
				if(empty($message)) continue;
				if(empty($message['text'])) continue;
				echo '.';
				
				// change <@U38A3DE9> into levelsio
				if(stripos($message['text'],'<@')!==false) {
					$usersInMessage=explode('<@',$message['text']);
					foreach($usersInMessage as $userInMessage) {
						$array=explode('>',$userInMessage);
						$userHandleInBrackets=$array[0];
						$array=explode('|',$array[0]);
						$userInMessage=$array[0];
						$username=$array[1];
						if(empty($username)) {
							$username=$usersById[$userInMessage]['name'];
						}
						$message['text']=str_replace('<@'.$userHandleInBrackets.'>','@'.$username,$message['text']);
					}
				}

				// change <#U38A3DE9> into #_chiang-mai
				if(stripos($message['text'],'<#')!==false) {
					$channelsInMessage=explode('<#',$message['text']);
					foreach($channelsInMessage as $channelInMessage) {
						$array=explode('>',$channelInMessage);
						$channelHandleInBrackets=$array[0];
						$array=explode('|',$array[0]);
						$channelInMessage=$array[0];
						$channelNameInMessage=$array[1];
						if(empty($username)) {
							$channelNameInMessage=$channelsById[$channelInMessage]['name'];
						}
						if(!empty($username)) {
							$message['text']=str_replace('<#'.$channelHandleInBrackets.'>','#'.$channelNameInMessage,$message['text']);
						}
					}
				}
				// change <http://url> into link
				if(stripos($message['text'],'<http')!==false) {
					$linksInMessage=explode('<http',$message['text']);
					foreach($linksInMessage as $linkInMessage) {
						$array=explode('>',$linkInMessage);
						$linkTotalInBrackets=$array[0];
						$array=explode('|',$array[0]);
						$linkInMessage=$array[0];
						$message['text']=str_replace('<http'.$linkTotalInBrackets.'>','<a href="http'.$linkInMessage.'">http'.$linkInMessage.'</a>',$message['text']);
					}
				}

				// change @levelsio has joined the channel into
				// @levelsio\n has joined #channel
				if(stripos($message['text'],'has joined the channel')!==false) {
					$message['text']=str_replace('the channel','#'.$channelName,$message['text']);
					$message['text']=str_replace('@'.$usersById[$message['user']]['name'].' ','',$message['text']);
				}

				$array=explode('.',$message['ts']);
				$time=$array[0];

				$message['text']=utf8_decode($message['text']);
				
				$htmlMessage='';
				$htmlMessage.='<div><img src="'.$usersById[$message['user']]['profile']['image_72'].'" /><div class="message"><div class="username">'.$usersById[$message['user']]['name'].'</div><div class="time">'.date('Y-m-d H:i',$message['ts']).'</div><div class="msg">'.$message['text']."</div></div></div><br/>\n";
				$htmlMessages.=$htmlMessage;
			}

			$htmlMessages.='</div></body></html>';
			file_put_contents($channelHtmlFile,$htmlMessages);
			$mostRecentChannelTimestamps[$channelName]=$mostRecentChannelTimestamp;
			echo "\n";
		}
		asort($mostRecentChannelTimestamps);
		$mostRecentChannelTimestamps=array_reverse($mostRecentChannelTimestamps);
	// </generate html from channel logs>

	// <make index html>
		$html='<html><body><style>'.$stylesheet.'</style><div class="messages">';
		foreach($mostRecentChannelTimestamps as $channel => $timestamp) {
			$html.='<a href="./'.$channel.'.html">#'.$channel.'</a> '.date('Y-m-d H:i',$timestamp).'<br/>'."\n";
		}
		$html.='</div></body></html>';
		file_put_contents($htmlDir.'/index.html',$html);
	// </make index html>

?>