Skip to content

Commit 2e82145

Browse files
committed
Tweet Nest 0.8 launch
0 parents  commit 2e82145

39 files changed

+3946
-0
lines changed

.htaccess

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
RewriteEngine On
2+
RewriteRule ^sort/?$ ./sort.php [L]
3+
RewriteRule ^favorites/?$ ./favorites.php [L]
4+
RewriteRule ^search/?$ ./search.php [L]
5+
RewriteRule ^([0-9]+)/([0-9]+)/?$ ./month.php?y=$1&m=$2
6+
RewriteRule ^([0-9]+)/([0-9]+)/([0-9]+)/?$ ./day.php?y=$1&m=$2&d=$3

LICENSE.txt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (c) 2010 Andy Graulund <andy@graulund> <pongsocket.com>
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is
8+
furnished to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in
11+
all copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
THE SOFTWARE.

README.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
HI! THIS IS TWEET NEST.
2+
3+
Tweet Nest is a browsable, searchable and easily customizable archive and backup for your tweets, made in PHP. It runs on a web server. It requires the following:
4+
5+
* PHP 5.2 or higher (or 5.1 with the PECL JSON module installed)
6+
* MySQL 4.1 or higher
7+
8+
To figure out how to install it, please point your browser to:
9+
10+
http://pongsocket.com/tweetnest/
11+
12+
And go to the "Installation" section.
13+
14+
Thanks!
15+
16+
Andy Graulund
17+
pongsocket.com

RENAME-ME.htaccess

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
RewriteEngine On
2+
RewriteRule ^sort/?$ ./sort.php [L]
3+
RewriteRule ^favorites/?$ ./favorites.php [L]
4+
RewriteRule ^search/?$ ./search.php [L]
5+
RewriteRule ^([0-9]+)/([0-9]+)/?$ ./month.php?y=$1&m=$2
6+
RewriteRule ^([0-9]+)/([0-9]+)/([0-9]+)/?$ ./day.php?y=$1&m=$2&d=$3

day.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
// PONGSOCKET TWEET ARCHIVE
3+
// Day page
4+
5+
require "inc/preheader.php";
6+
7+
$m = ltrim($_GET['m'], "0");
8+
$d = ltrim($_GET['d'], "0");
9+
if(!is_numeric($d) || !is_numeric($m) || !is_numeric($_GET['y']) || (is_numeric($d) && ($d > 31 || $d < 1)) || (is_numeric($m) && ($m > 12 || $m < 1)) || (is_numeric($_GET['y']) && $_GET['y'] < 2000)){ errorPage("Invalid year, month or day. Please specify a valid date."); }
10+
11+
$q = $db->query("SELECT `".DTP."tweets`.*, `".DTP."tweetusers`.`screenname`, `".DTP."tweetusers`.`realname`, `".DTP."tweetusers`.`profileimage` FROM `".DTP."tweets` LEFT JOIN `".DTP."tweetusers` ON `".DTP."tweets`.`userid` = `".DTP."tweetusers`.`userid` WHERE YEAR(FROM_UNIXTIME(`time`" . DB_OFFSET . ")) = '" . s($_GET['y']) . "' AND MONTH(FROM_UNIXTIME(`time`" . DB_OFFSET . ")) = '" . s($m) . "' AND DAY(FROM_UNIXTIME(`time`" . DB_OFFSET . ")) = '" . s($d) . "' ORDER BY `".DTP."tweets`.`time` DESC");
12+
13+
$selectedDate = array("y" => $_GET['y'], "m" => $m, "d" => $d);
14+
$pageTitle = date("F jS, Y", mktime(1,0,0,$m,$d,$_GET['y']));
15+
$preBody = displayDays($_GET['y'], $m);
16+
17+
require "inc/header.php";
18+
echo tweetsHTML($q, "day");
19+
require "inc/footer.php";

extensions/images.php

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
// PONGSOCKET TWEET ARCHIVE
3+
// Image display extension
4+
5+
if(!function_exists("imgid")){
6+
function imgid($path){
7+
$m = array();
8+
preg_match("@/([a-z0-9]+).*@i", $path, $m);
9+
if(count($m) > 0){
10+
return $m[1];
11+
}
12+
return false;
13+
}
14+
}
15+
16+
class Extension_Images {
17+
public function enhanceTweet($tweet){
18+
$imgs = array();
19+
$links = findURLs($tweet['text']);
20+
foreach($links as $link => $l){
21+
if(is_array($l) && array_key_exists("host", $l) && array_key_exists("path", $l)){
22+
$domain = domain($l['host']);
23+
$imgid = imgid($l['path']);
24+
if($imgid){
25+
if($domain == "twitpic.com"){
26+
$imgs[$link] = "http://twitpic.com/show/thumb/" . $imgid;
27+
}
28+
if($domain == "yfrog.com"){
29+
$imgs[$link] = "http://yfrog.com/" . $imgid . ".th.jpg";
30+
}
31+
if($domain == "tweetphoto.com" || $domain == "pic.gd"){
32+
$imgs[$link] = "http://tweetphotoapi.com/api/TPAPI.svc/imagefromurl?size=thumbnail&url=" . $link;
33+
}
34+
if($domain == "twitgoo.com"){
35+
$values = simplexml_load_string(getURL("http://twitgoo.com/api/message/info/" . $imgid));
36+
$imgs[$link] = (string) $values->thumburl;
37+
}
38+
if($domain == "img.ly"){
39+
$imgs[$link] = "http://img.ly/show/thumb/" . $imgid;
40+
}
41+
if($domain == "imgur.com"){
42+
$imgs[$link] = "http://i.imgur.com/" . $imgid . "s.jpg";
43+
}
44+
if($domain == "twitvid.com"){
45+
$imgs[$link] = "http://images.twitvid.com/" . $imgid . ".jpg";
46+
}
47+
}
48+
}
49+
}
50+
if(count($imgs) > 0){
51+
$tweet['extra']['imgs'] = $imgs;
52+
}
53+
return $tweet;
54+
}
55+
56+
public function displayTweet($d, $tweet){
57+
@$tweetextra = unserialize($tweet['extra']);
58+
if(array_key_exists("imgs", $tweetextra)){
59+
preg_match("/^([\t]+)</", $d, $m); $x = $m[1];
60+
$ds = explode("\n", $d, 2);
61+
$imgd = ""; $i = 1; $is = array();
62+
foreach($tweetextra['imgs'] as $link => $img){
63+
$imgd .=
64+
$x . "\t<a class=\"pic pic-" . s($i) . "\" href=\"" . s($link) . "\">" .
65+
"<img src=\"" . s($img) . "\" alt=\"\" /></a>\n";
66+
$is[$link] = $i++;
67+
}
68+
foreach($is as $link => $i){
69+
$ds[1] = preg_replace(
70+
"/class=\"([^\"]*)\" href=\"" . preg_quote(s($link), "/") . "\"/",
71+
"class=\"$1 picl picl-" . s($i) . "\" href=\"" . s($link) . "\"",
72+
$ds[1]
73+
);
74+
}
75+
$d = implode("\n", array($ds[0], rtrim($imgd, "\n"), $ds[1]));
76+
}
77+
return $d;
78+
}
79+
}
80+
81+
$o = new Extension_Images();

favorites.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
// PONGSOCKET TWEET ARCHIVE
3+
// Favorites page
4+
5+
require "inc/preheader.php";
6+
7+
$filterMode = "favorites";
8+
9+
$month = false;
10+
if(!empty($_GET['m']) && !empty($_GET['y'])){
11+
$m = ltrim($_GET['m'], "0");
12+
if(is_numeric($m) && $m >= 1 && $m <= 12 && is_numeric($_GET['y']) && $_GET['y'] >= 2000){
13+
$month = true;
14+
$selectedDate = array("y" => $_GET['y'], "m" => $m, "d" => 0);
15+
}
16+
}
17+
18+
$mq = $db->query("SELECT MONTH(FROM_UNIXTIME(`time`" . DB_OFFSET . ")) AS m, YEAR(FROM_UNIXTIME(`time`" . DB_OFFSET . ")) AS y, COUNT(*) as c FROM `".DTP."tweets` WHERE `".DTP."tweets`.`favorite` > 0 GROUP BY y, m ORDER BY y DESC, m DESC");
19+
while($d = $db->fetch($mq)){ $highlightedMonths[$d['y'] . "-" . $d['m']] = $d['c']; }
20+
21+
$q = $db->query("SELECT `".DTP."tweets`.*, `".DTP."tweetusers`.`screenname`, `".DTP."tweetusers`.`realname`, `".DTP."tweetusers`.`profileimage` FROM `".DTP."tweets` LEFT JOIN `".DTP."tweetusers` ON `".DTP."tweets`.`userid` = `".DTP."tweetusers`.`userid` WHERE `".DTP."tweets`.`favorite` > 0" . ($month ? " AND YEAR(FROM_UNIXTIME(`time`" . DB_OFFSET . ")) = '" . $db->s($_GET['y']) . "' AND MONTH(FROM_UNIXTIME(`time`" . DB_OFFSET . ")) = '" . $db->s($m) . "'" : "") . " ORDER BY `".DTP."tweets`.`time` DESC");
22+
23+
$pageHeader = "Favorite tweets" . ($month ? " from " . date("F Y", mktime(1,0,0,$m,1,$_GET['y'])) : "");
24+
25+
require "inc/header.php";
26+
echo tweetsHTML($q);
27+
require "inc/footer.php";

inc/class.db.php

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
<?php
2+
// PONGSOCKET TWEET ARCHIVE
3+
// DB class
4+
// By Andy Graulund
5+
6+
7+
class DB {
8+
public $res = null;
9+
public $type = "";
10+
public $on = false;
11+
public $conn = false;
12+
public $mysqli = false;
13+
private $config = null;
14+
15+
public function __construct($type, $config){
16+
if(in_array(strtolower(trim($type)), array("mysql" /* more to be added later */))){
17+
$this->type = strtolower(trim($type));
18+
if(!empty($config['hostname']) && !empty($config['username']) && !empty($config['password']) && !empty($config['database'])){
19+
$this->config = $config;
20+
$this->connect();
21+
} else {
22+
throw new Exception("Not enough config information.");
23+
}
24+
} else {
25+
throw new Exception("Unsupported database type.");
26+
}
27+
}
28+
29+
protected function connect(){
30+
switch($this->type){
31+
case "mysql":
32+
// Check for MySQLi
33+
$this->mysqli = extension_loaded("mysqli");
34+
if(!$this->mysqli){
35+
$prefix = (PHP_SHLIB_SUFFIX === "dll") ? "php_" : "";
36+
if(@dl($prefix . "mysqli." . PHP_SHLIB_SUFFIX)){
37+
$this->mysqli = extension_loaded("mysqli");
38+
}
39+
}
40+
try {
41+
$this->on = true;
42+
$this->res = $this->mysqli ?
43+
new mysqli($this->config['hostname'], $this->config['username'], $this->config['password'], $this->config['database']) :
44+
mysql_connect($this->config['hostname'], $this->config['username'], $this->config['password']);
45+
if(!$this->mysqli){ mysql_select_db($this->config['database'], $this->res); }
46+
$this->conn = true;
47+
if($this->mysqli && $this->res->connect_error){
48+
$this->conn = false;
49+
throw new Exception("Could not connect to the DB: " . $this->res->connect_error);
50+
} else {
51+
if(!$this->res){
52+
$this->conn = false;
53+
throw new Exception("Could not connect to the DB: " . mysql_error($this->res));
54+
}
55+
}
56+
} catch(Exception $e){
57+
throw new Exception("Could not connect to the DB: " . $e->getMessage());
58+
}
59+
break;
60+
}
61+
}
62+
63+
public function query($query, $result = MYSQLI_STORE_RESULT){
64+
return $this->mysqli ? $this->res->query($query, $result) : mysql_query($query, $this->res);
65+
}
66+
67+
public function fetch($result = NULL){
68+
if($this->mysqli){
69+
if(!$result || !is_object($result)){ return false; }
70+
return $result->fetch_assoc();
71+
} else {
72+
return mysql_fetch_assoc($result);
73+
}
74+
}
75+
76+
public function numRows($result = NULL){
77+
if($this->mysqli){
78+
if(!$result || !is_object($result)){ return false; }
79+
return $result->num_rows;
80+
} else {
81+
return mysql_num_rows($result);
82+
}
83+
}
84+
85+
public function insertID(){
86+
return $this->mysqli ? $this->res->insert_id : mysql_insert_id($this->res);
87+
}
88+
89+
public function error(){
90+
return $this->mysqli ? $this->res->error : mysql_error($this->res);
91+
}
92+
93+
public function s($str){
94+
return $this->mysqli ? $this->res->real_escape_string($str) : mysql_real_escape_string($str, $this->res);
95+
}
96+
97+
public function clientVersion(){
98+
return $this->mysqli ? $this->res->get_client_info() : mysql_get_client_info();
99+
}
100+
101+
public function serverVersion(){
102+
return $this->mysqli ? $this->res->server_info : mysql_get_server_info();
103+
}
104+
105+
public function reconnect(){
106+
if($this->mysqli){
107+
$this->res->kill($this->res->thread_id);
108+
$this->res->close();
109+
} else {
110+
mysql_close();
111+
}
112+
$this->res = null;
113+
$this->conn = false;
114+
$this->connect();
115+
}
116+
}

0 commit comments

Comments
 (0)