Initial Files

This commit is contained in:
Win 2025-05-15 20:39:55 +07:00
parent c0259f00db
commit 10ff6fc517
79 changed files with 62055 additions and 0 deletions

BIN
admin/.DS_Store vendored Executable file

Binary file not shown.

BIN
admin/._.DS_Store Executable file

Binary file not shown.

21
admin/assets/css/login.css Executable file
View File

@ -0,0 +1,21 @@
html, body {
background-color: #f1f1f1;
font-family: Arial, Helvetica, sans-serif;
}
.center {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
border: 5px solid gray;
padding: 10px;
}
#main {
background-color: #fff;
width: 400px;
padding: 5px;
text-align: center;
}

20
admin/assets/css/style.css Executable file
View File

@ -0,0 +1,20 @@
html, body {
height: 100%;
font-family: Arial, Helvetica, sans-serif;
}
.container {
min-height: 100%;
position: relative;
}
.postFormContainer .postBodyContainer {
padding-right: 10px;
}
.postFormContainer .postBodyContainer #postBodyInput {
width: 100%;
font-family: Arial, Helvetica, sans-serif;
}

54
admin/forms/delete.php Executable file
View File

@ -0,0 +1,54 @@
<?php
include_once("../includes/config.php");
function generateRandomString($length = 11) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
$postUrlGen = generateRandomString();
// check if the user is logged in
if(!$_SESSION["username"]) {
header("Location: ../login.php");
}
// check if the request is a post request
if($_SERVER["REQUEST_METHOD"] == "POST") {
if(isset($_POST["deletePostSubmit"])) {
// declare variables
$postBody = htmlspecialchars(strip_tags($_POST["postBodyInput"]));
$author = "winsdominoes";
// check if the post body is empty
if(!$postBody) {
die("No post body was entered");
}
// pdo prepare statement
$stmt = $con->prepare("DELETE FROM posts WHERE")
$stmt->bindParam(":url", $postUrl)
// $stmt = $con->prepare("INSERT INTO posts (url, content, author) VALUES (:url, :content, :author)");
//$stmt->bindParam(":url", $postUrlGen);
//$stmt->bindParam(":content", $postBody);
//$stmt->bindParam(":author", $author);
$stmt->execute();
// check if query was successful
if($stmt) {
header("Location: ../index.php");
} else {
die("Something went wrong");
}
}
}
?>

49
admin/forms/post.php Executable file
View File

@ -0,0 +1,49 @@
<?php
include_once("../includes/config.php");
function generateRandomString($length = 11) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
$postUrlGen = generateRandomString();
// check if the user is logged in
if(!$_SESSION["username"]) {
header("Location: ../login.php");
}
// check if the request is a post request
if($_SERVER["REQUEST_METHOD"] == "POST") {
if(isset($_POST["postSubmit"])) {
// declare variables
$postBody = htmlspecialchars(strip_tags($_POST["postBodyInput"]));
$author = "winsdominoes";
// check if the post body is empty
if(!$postBody) {
die("No post body was entered");
}
// pdo prepare statement
$stmt = $con->prepare("INSERT INTO posts (url, content, author) VALUES (:url, :content, :author)");
$stmt->bindParam(":url", $postUrlGen);
$stmt->bindParam(":content", $postBody);
$stmt->bindParam(":author", $author);
$stmt->execute();
// check if query was successful
if($stmt) {
header("Location: ../index.php");
} else {
die("Something went wrong");
}
}
}
?>

BIN
admin/includes/._header.php Executable file

Binary file not shown.

20
admin/includes/config.php Executable file
View File

@ -0,0 +1,20 @@
<?php
ob_start(); //Turns on output buffering
session_start();
date_default_timezone_set("Asia/Bangkok");
// attempt to connect to the database via PDO
$servername = "localhost";
$username = "posts";
$password = "XL8YkuMhUncCG3SYs2725KQBaETHvLtnJDg9AE3kVAQe27wxmegyDKHBf3sSmu54yLzNknC2ynsrjRDW2RWXrXqUFh8em9pzBXYVMPg48KFQ6kMuMvj5bNTUpSPkx3zN";
try {
$con = new PDO("mysql:host=$servername;dbname=blogs", $username, $password);
// set the PDO error mode to exception
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
echo "Connection failed: " . $e->getMessage();
}
header('Content-Type: text/html; charset=utf-8');
?>

2
admin/includes/footer.php Executable file
View File

@ -0,0 +1,2 @@
</body>
</html>

30
admin/includes/header.php Executable file
View File

@ -0,0 +1,30 @@
<?php
// echo all errors
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
include_once("config.php");
include_once("../includes/classes/Post.php");
include_once("../includes/classes/Markdown.php");
if(!$_SESSION["username"]) {
header("Location: login.php");
} else {
$username = $_SESSION["username"];
}
$Parsedown = new Parsedown();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Win's Personal Feed - Admin</title>
<link rel="stylesheet" href="assets/css/style.css">
</head>
<body>

54
admin/index.php Executable file
View File

@ -0,0 +1,54 @@
<?php
include_once("includes/header.php");
?>
<style>
html, body {
background-color: #121212;
color: #fff;
}
</style>
<div class="container">
<div class="postFormContainer">
<h1>What's going on!?</h1>
<!-- form for posting something -->
<form action="forms/post.php" method="post">
<div class="postBodyContainer">
<textarea name="postBodyInput" id="postBodyInput" rows="10" placeholder="What's up, Win!"></textarea>
</div>
<br><button type="submit" name="postSubmit">Post</button>
</form>
</div>
<br>
<div class="postsContainer">
<h2><u>Your Posts</u></h2>
<?php
$stmt = $con->prepare("SELECT * FROM posts ORDER BY id DESC LIMIT 10");
$stmt->execute();
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$post = new Post($con, $row);
$postUrl = $post->getPostUrl();
$postAuthor = $post->getPostAuthor();
$postedDate = $post->getPublishedDate();
$postContent = $Parsedown->text($post->getPostContent());
$item = "<span id='content' style='font-size: 12px;'><b>" . $postAuthor . " · <span style='color: gray'>" . $postedDate . " GMT +7</b></span></span>
<p class='card-text'>" . $postContent . "</p>
<a href='status.php?url=$postUrl' class='text-decoration-none' style='font-size: 10px;'>View Post</a>
<form action='forms/delete.php' method='post'>
<button type='submit' name='deletePostSubmit'>Delete</button>
</form>
<hr>";
echo $item;
}
?>
</div>
</div>
<?php
include_once("includes/footer.php");
?>

64
admin/login.php Executable file
View File

@ -0,0 +1,64 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Feed - Login</title>
<link rel="stylesheet" href="assets/css/login.css">
</head>
<?php
include_once("includes/config.php");
if(isset($_POST["submit"])) {
// declare functions
function generateRandomString($length = 64) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
$randomString = generateRandomString();
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// declare some variables
$username = htmlspecialchars(strip_tags($_POST["username"]));
$password = htmlspecialchars(strip_tags($_POST["password"]));
if(!$username && !$password) {
die("No Username was entered");
} else if ($username == "administrator" && $password == "5fxDTjgUykN8X374Wduu7AGZGNBhccMD4jCQ2W7694rAEV4KemB9Q4kY2tWKjUye") {
$_SESSION["username"] = $randomString;
header("Location: index.php");
} else {
header("Location: login.php");
}
}
}
?>
<body>
<div class="content">
<div id="main" class="center">
<h1>Win's Panel</h1>
<form action="login.php" method="post" enctype="multipart/form-data">
Username: <input type="text" name="username" placeholder="Username...">
<br><br>
Password: <input type="password" name="password" placeholder="Password...">
<br><br>
<button id="submit" type="submit" name="submit">Submit</button>
</form>
</div>
</div>
</body>
</html>

4997
assets/bootstrap/css/bootstrap-grid.css vendored Executable file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

7
assets/bootstrap/css/bootstrap-grid.min.css vendored Executable file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4996
assets/bootstrap/css/bootstrap-grid.rtl.css vendored Executable file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

426
assets/bootstrap/css/bootstrap-reboot.css vendored Executable file
View File

@ -0,0 +1,426 @@
/*!
* Bootstrap Reboot v5.0.0-beta3 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors
* Copyright 2011-2021 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #212529;
background-color: #fff;
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
background-color: currentColor;
border: 0;
opacity: 0.25;
}
hr:not([size]) {
height: 1px;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title],
abbr[data-bs-original-title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-left: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-left: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.2em;
background-color: #fcf8e3;
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: #0d6efd;
text-decoration: underline;
}
a:hover {
color: #0a58ca;
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
font-size: 1em;
direction: ltr /* rtl:ignore */;
unicode-bidi: bidi-override;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: #d63384;
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.2rem 0.4rem;
font-size: 0.875em;
color: #fff;
background-color: #212529;
border-radius: 0.2rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
font-weight: 700;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: #6c757d;
text-align: left;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]::-webkit-calendar-picker-indicator {
display: none;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: left;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
font-size: calc(1.275rem + 0.3vw);
line-height: inherit;
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: left;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
outline-offset: -2px;
-webkit-appearance: textfield;
}
/* rtl:raw:
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
*/
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::file-selector-button {
font: inherit;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.css.map */

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,8 @@
/*!
* Bootstrap Reboot v5.0.0-beta3 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors
* Copyright 2011-2021 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){h1{font-size:2.5rem}}h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){h2{font-size:2rem}}h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){h3{font-size:1.75rem}}h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){h4{font-size:1.5rem}}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:.875em}mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}
/*# sourceMappingURL=bootstrap-reboot.min.css.map */

File diff suppressed because one or more lines are too long

423
assets/bootstrap/css/bootstrap-reboot.rtl.css vendored Executable file
View File

@ -0,0 +1,423 @@
/*!
* Bootstrap Reboot v5.0.0-beta3 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors
* Copyright 2011-2021 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #212529;
background-color: #fff;
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
background-color: currentColor;
border: 0;
opacity: 0.25;
}
hr:not([size]) {
height: 1px;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title],
abbr[data-bs-original-title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-right: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-right: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.2em;
background-color: #fcf8e3;
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: #0d6efd;
text-decoration: underline;
}
a:hover {
color: #0a58ca;
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
font-size: 1em;
direction: ltr ;
unicode-bidi: bidi-override;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: #d63384;
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.2rem 0.4rem;
font-size: 0.875em;
color: #fff;
background-color: #212529;
border-radius: 0.2rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
font-weight: 700;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: #6c757d;
text-align: right;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]::-webkit-calendar-picker-indicator {
display: none;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: right;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
font-size: calc(1.275rem + 0.3vw);
line-height: inherit;
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: right;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
outline-offset: -2px;
-webkit-appearance: textfield;
}
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::file-selector-button {
font: inherit;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.rtl.css.map */

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,8 @@
/*!
* Bootstrap Reboot v5.0.0-beta3 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors
* Copyright 2011-2021 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){h1{font-size:2.5rem}}h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){h2{font-size:2rem}}h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){h3{font-size:1.75rem}}h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){h4{font-size:1.5rem}}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-right:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-right:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:.875em}mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:right}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:right;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:right}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}[type=email],[type=number],[type=tel],[type=url]{direction:ltr}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}
/*# sourceMappingURL=bootstrap-reboot.rtl.min.css.map */

File diff suppressed because one or more lines are too long

4752
assets/bootstrap/css/bootstrap-utilities.css vendored Executable file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4743
assets/bootstrap/css/bootstrap-utilities.rtl.css vendored Executable file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

10819
assets/bootstrap/css/bootstrap.css vendored Executable file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

7
assets/bootstrap/css/bootstrap.min.css vendored Executable file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

10795
assets/bootstrap/css/bootstrap.rtl.css vendored Executable file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

7
assets/bootstrap/css/bootstrap.rtl.min.css vendored Executable file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

6714
assets/bootstrap/js/bootstrap.bundle.js vendored Executable file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

7
assets/bootstrap/js/bootstrap.bundle.min.js vendored Executable file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4944
assets/bootstrap/js/bootstrap.esm.js vendored Executable file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

7
assets/bootstrap/js/bootstrap.esm.min.js vendored Executable file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4993
assets/bootstrap/js/bootstrap.js vendored Executable file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

7
assets/bootstrap/js/bootstrap.min.js vendored Executable file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

91
assets/css/style.css Executable file
View File

@ -0,0 +1,91 @@
html, body {
font-family: Arial, Helvetica, sans-serif;
color: #eee;
background: #121212;
}
pre {
white-space: pre-wrap; /* Since CSS 2.1 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
}
a {
color: #eee;
text-decoration: none;
}
a:hover {
color: gray;
}
/* MARQUEE */
.marquee {
height: 50px;
overflow: hidden;
position: relative;
background: #fefefe;
color: #333;
border: 1px solid #4a4a4a;
}
.marquee p {
position: absolute;
width: 100%;
height: 100%;
margin: 0;
line-height: 50px;
text-align: center;
-moz-transform: translateX(100%);
-webkit-transform: translateX(100%);
transform: translateX(100%);
-moz-animation: scroll-left 2s linear infinite;
-webkit-animation: scroll-left 2s linear infinite;
animation: scroll-left 20s linear infinite;
}
@-moz-keyframes scroll-left {
0% {
-moz-transform: translateX(100%);
}
100% {
-moz-transform: translateX(-100%);
}
}
@-webkit-keyframes scroll-left {
0% {
-webkit-transform: translateX(100%);
}
100% {
-webkit-transform: translateX(-100%);
}
}
@keyframes scroll-left {
0% {
-moz-transform: translateX(100%);
-webkit-transform: translateX(100%);
transform: translateX(100%);
}
100% {
-moz-transform: translateX(-100%);
-webkit-transform: translateX(-100%);
transform: translateX(-100%);
}
}
.header {
margin-top: 10px;
}
.leftSection, .mainSection, .rightSection {
margin-top: 10px;
}
.post-text {
font: normal normal 13px Arial, Tahoma, Helvetica, FreeSans, sans-serif;
}

57
assets/css/twitter.css Executable file
View File

@ -0,0 +1,57 @@
.tweet-list {
list-style: outside none;
padding-left: 0;
}
.tweet-list li {
padding: 10px;
border: 1px solid rgb(47, 51, 54);
border-radius: 0px;
margin-bottom: 5px;
}
.tweet-list .is-retweet {
}
.tweet-list .is-reply {
}
.user-avatar {
float: left;
padding-right: 10px;
}
.user-account {
float: left;
margin: 3px 0 0;
}
.user-name {
display: block;
}
.tweet-date {
float: right;
}
.tweet-text {
clear: both;
margin: 0;
padding: 10px 0;
}
.tweet-details {
}
.link-reply-to,
.retweeter {
font-style: italic;
}
.visitor-retweeted .action-retweet,
.visitor-favorited .action-favorite {
color: #999;
}

BIN
assets/images/logo.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

59
assets/js/twitter.js Executable file
View File

@ -0,0 +1,59 @@
//---------------------------- Twitter functions
var twitter = {
$list: $('#tweet-list'),
init: function() {
twttr.ready(function(twttr) {
twitter.retweet();
twitter.favorite();
twitter.openStatus();
});
},
retweet: function() {
// add a class to the status li when a visitor successfully retweets a tweet
twttr.events.bind('retweet', function(e) {
var retweeted_tweet_id = e.data.source_tweet_id,
$thisTweet = twitter.$list.find('#tweetid-' + retweeted_tweet_id);
$thisTweet.addClass('visitor-retweeted');
});
},
favorite: function() {
// add a class to the status li when a visitor successfully favorites a tweet
twttr.events.bind('favorite', function(e) {
var favorited_tweet_id = e.data.tweet_id,
$thisTweet = twitter.$list.find('#tweetid-' + favorited_tweet_id);
$thisTweet.addClass('visitor-favorited');
});
},
openStatus: function() {
// open status permalinks in a popup window
$('.permalink-status').on('click', function(e) {
var height = 450,
width = 660,
top = (screen.height / 2) - (height / 2)
left = (screen.width / 2) - (width / 2);
e.preventDefault();
window.open(
this.href,
'tweetStatus',
'height=' + height + ', width=' + width + ', toolbar=0, status=0, top=' + top + ', left=' + left
);
});
}
};
//---------------------------- Document Ready
$(document).ready(function() {
twitter.init();
});

37
feed.php Executable file
View File

@ -0,0 +1,37 @@
<?php
include_once("includes/config.php");
// PDO query
$postQuery = $con->prepare("SELECT * FROM posts ORDER BY id DESC");
$postQuery->execute();
header("Content-type: text/xml");
echo "<?xml version='1.0' encoding='UTF-8'?>
<rss version='2.0'>
<channel>
<title>Win's Posts RSS Feed</title>
<link>https://posts.winscloud.net/</link>
<description>Win's Posts - The homepage of Win's Life</description>
<language>en-us</language>";
while($result = $postQuery->fetch(PDO::FETCH_ASSOC)) {
$postUrl = $result["url"];
$postContent = $result["content"];
$postAuthor = $result["author"];
// $rawDate = $result["published"];
$postDate = date('M j Y g:i A', strtotime($result["published"]));
echo "<item>
<title>Post by $postAuthor</title>
<link>https://posts.winscloud.net/status?url=$postUrl</link>
<guid>https://posts.winscloud.net/status?url=$postUrl</guid>
<pubDate>$postDate</pubDate>
<description>$postContent</description>
</item>";
}
echo "</channel></rss>";
?>

BIN
includes/.DS_Store vendored Executable file

Binary file not shown.

BIN
includes/._.DS_Store Executable file

Binary file not shown.

BIN
includes/._config.php Executable file

Binary file not shown.

BIN
includes/._header.php Executable file

Binary file not shown.

BIN
includes/._postHeader.php Executable file

Binary file not shown.

BIN
includes/classes/._Post.php Executable file

Binary file not shown.

48
includes/classes/Comment.php Executable file
View File

@ -0,0 +1,48 @@
<?php
class Comment {
private $con, $sqlData;
public function __construct($con, $input) {
$this->con = $con;
if(is_array($input)) {
$this->sqlData = $input;
}
else {
// $query = $this->con->prepare("SELECT * FROM videos WHERE id = :id OR url = :url");
$query = $this->con->prepare("SELECT * FROM comments WHERE comments_url = :url");
$query->bindParam(":url", $input);
$query->execute();
$this->sqlData = $query->fetch(PDO::FETCH_ASSOC);
}
}
public function getCommentId() {
return $this->sqlData["id"];
}
public function getCommentUrl() {
return $this->sqlData["comment_url"];
}
public function getCommentAuthor() {
return $this->sqlData["comment_author"];
}
public function getCommentBody() {
return $this->sqlData["comment_body"];
}
public function getCommentTimestamp() {
$rawDate = $this->sqlData["comment_timestamp"];
return date('M j Y g:i A', strtotime($rawDate));
}
public function getCommentPostUrl() {
return $this->sqlData["comment_onPost"];
}
}
?>

1994
includes/classes/Markdown.php Executable file

File diff suppressed because it is too large Load Diff

73
includes/classes/Post.php Executable file
View File

@ -0,0 +1,73 @@
<?php
class Post {
private $con, $sqlData;
public function __construct($con, $input) {
$this->con = $con;
if(is_array($input)) {
$this->sqlData = $input;
}
else {
// $query = $this->con->prepare("SELECT * FROM videos WHERE id = :id OR url = :url");
$query = $this->con->prepare("SELECT * FROM posts WHERE url = :url");
$query->bindParam(":url", $input);
$query->execute();
$this->sqlData = $query->fetch(PDO::FETCH_ASSOC);
}
}
public function getPostId() {
return $this->sqlData["id"];
}
public function getPostUrl() {
return $this->sqlData["url"];
}
public function getPostContent() {
return $this->sqlData["content"];
}
public function getPostAuthor() {
return $this->sqlData["author"];
}
public function getPublishedDate() {
$dateStr = $this->sqlData["published"];
// return date('M j Y g:i A', strtotime($rawDate));
$timestamp = strtotime($dateStr);
$day = 60 * 60 * 24;
$today = time(); // current unix time
$since = $today - $timestamp;
# If it's been less than 1 day since the tweet was posted, figure out how long ago in seconds/minutes/hours
if (($since / $day) < 1) {
$timeUnits = array(
array(60 * 60, 'h'),
array(60, 'm'),
array(1, 's')
);
for ($i = 0, $n = count($timeUnits); $i < $n; $i++) {
$seconds = $timeUnits[$i][0];
$unit = $timeUnits[$i][1];
if (($count = floor($since / $seconds)) != 0) {
break;
}
}
return "$count{$unit} ago";
# If it's been a day or more, return the date: day (without leading 0) and 3-letter month
} else {
return date('M j Y g:i A', strtotime($dateStr));
}
}
}
?>

View File

@ -0,0 +1,162 @@
<?php
/**
* twitter-timeline-php : Twitter API 1.1 user timeline implemented with PHP, a little JavaScript, and web intents
*
* @package twitter-timeline-php
* @author Kim Maida <contact@kim-maida.com>
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
* @link http://github.com/kmaida/twitter-timeline-php
* @credits Based on a mish-mash of code from Rivers, Jimbo / James Mallison, and others at <http://stackoverflow.com/questions/12916539/simplest-php-example-for-retrieving-user-timeline-with-twitter-api-version-1-1>
*
**/
if (class_exists('TwitterAPITimeline') === false) {
class TwitterAPITimeline
{
private $consumer_key;
private $consumer_secret;
private $oauth_access_token;
private $oauth_access_token_secret;
private $getfield;
protected $oauth;
public $url;
public function __construct(array $settings)
{
if (!in_array('curl', get_loaded_extensions()))
{
throw new Exception('You need to install cURL, see: http://curl.haxx.se/docs/install.html');
}
if (!isset($settings['oauth_access_token'])
|| !isset($settings['oauth_access_token_secret'])
|| !isset($settings['consumer_key'])
|| !isset($settings['consumer_secret']))
{
throw new Exception('Make sure you are passing in the correct parameters');
}
$this->oauth_access_token = $settings['oauth_access_token'];
$this->oauth_access_token_secret = $settings['oauth_access_token_secret'];
$this->consumer_key = $settings['consumer_key'];
$this->consumer_secret = $settings['consumer_secret'];
}
public function setGetfield($string)
{
$search = array('#', ',', '+', ':');
$replace = array('%23', '%2C', '%2B', '%3A');
$string = str_replace($search, $replace, $string);
$this->getfield = $string;
return $this;
}
public function getGetfield()
{
return $this->getfield;
}
private function buildBaseString($baseURI, $method, $params)
{
$return = array();
ksort($params);
foreach($params as $key=>$value)
{
$return[] = "$key=" . $value;
}
return $method . "&" . rawurlencode($baseURI) . '&' . rawurlencode(implode('&', $return));
}
private function buildAuthorizationHeader($oauth)
{
$return = 'Authorization: OAuth ';
$values = array();
foreach($oauth as $key => $value)
{
$values[] = "$key=\"" . rawurlencode($value) . "\"";
}
$return .= implode(', ', $values);
return $return;
}
public function buildOauth($url)
{
$consumer_key = $this->consumer_key;
$consumer_secret = $this->consumer_secret;
$oauth_access_token = $this->oauth_access_token;
$oauth_access_token_secret = $this->oauth_access_token_secret;
$oauth = array(
'oauth_consumer_key' => $consumer_key,
'oauth_nonce' => time(),
'oauth_signature_method' => 'HMAC-SHA1',
'oauth_token' => $oauth_access_token,
'oauth_timestamp' => time(),
'oauth_version' => '1.0'
);
$getfield = $this->getGetfield();
if (!is_null($getfield))
{
$getfields = str_replace('?', '', explode('&', $getfield));
foreach ($getfields as $g)
{
$split = explode('=', $g);
$oauth[$split[0]] = $split[1];
}
}
$base_info = $this->buildBaseString($url, 'GET', $oauth);
$composite_key = rawurlencode($consumer_secret) . '&' . rawurlencode($oauth_access_token_secret);
$oauth_signature = base64_encode(hash_hmac('sha1', $base_info, $composite_key, true));
$oauth['oauth_signature'] = $oauth_signature;
$this->url = $url;
$this->oauth = $oauth;
return $this;
}
public function performRequest($return = true)
{
if (!is_bool($return))
{
throw new Exception('performRequest parameter must be true or false');
}
$header = array($this->buildAuthorizationHeader($this->oauth), 'Expect:');
$getfield = $this->getGetfield();
$options = array(
CURLOPT_HTTPHEADER => $header,
CURLOPT_HEADER => false,
CURLOPT_URL => $this->url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false
);
if ($getfield !== '')
{
$options[CURLOPT_URL] .= $getfield;
}
$feed = curl_init();
curl_setopt_array($feed, $options);
$json = curl_exec($feed);
curl_close($feed);
if ($return) { return $json; }
}
}
}
?>

209
includes/classes/twitter.php Executable file
View File

@ -0,0 +1,209 @@
<?php
/**
* twitter-timeline-php : Twitter API 1.1 user timeline implemented with PHP, a little JavaScript, and web intents
*
* @package twitter-timeline-php
* @author Kim Maida <contact@kim-maida.com>
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
* @link http://github.com/kmaida/twitter-timeline-php
* @credits Thank you to <http://viralpatel.net/blogs/twitter-like-n-min-sec-ago-timestamp-in-php-mysql/> for base for "time ago" calculations
*
**/
###############################################################
## SETTINGS
// Set access tokens <https://dev.twitter.com/apps/>
$settings = array(
'consumer_key' => "BbKsuZQ4HkpQpmQhuxPwpLxVW",
'consumer_secret' => "JhHo0x9D5nx89MI8jVsySvrJH8Vbbf7EgLoJPYYzAHpgGDOG5f",
'oauth_access_token' => "1018413731510771713-C7XwvicqmkyKBy8kf7TGagYXPgT0vP",
'oauth_access_token_secret' => "peQth0MMGURIw86b7s8y2efo8HOqCquRP0LfgOXWypfRN"
);
// Set API request URL and timeline variables if needed <https://dev.twitter.com/docs/api/1.1>
$url = 'https://api.twitter.com/1.1/statuses/user_timeline.json';
$twitterUsername = "WinsDominoes";
$tweetCount = 500;
// Use private tokens for development if they exist; delete when no longer necessary
$tokens = '_utils/tokens.php';
is_file($tokens) AND include $tokens;
// Require the OAuth class
require_once('twitter-api-oauth.php');
###############################################################
## MAKE GET REQUEST
$getfield = '?screen_name=' . $twitterUsername . '&count=' . $tweetCount;
$twitter = new TwitterAPITimeline($settings);
$json = $twitter->setGetfield($getfield) // Note: Set the GET field BEFORE calling buildOauth()
->buildOauth($url, $requestMethod)
->performRequest();
$twitter_data = json_decode($json, true); // Create an array with the fetched JSON data
###############################################################
## DO SOMETHING WITH THE DATA
//-------------------------------------------------------------- Format the time(ago) and date of each tweet
function timeAgo($dateStr) {
$timestamp = strtotime($dateStr);
$day = 60 * 60 * 24;
$today = time(); // current unix time
$since = $today - $timestamp;
# If it's been less than 1 day since the tweet was posted, figure out how long ago in seconds/minutes/hours
if (($since / $day) < 1) {
$timeUnits = array(
array(60 * 60, 'h'),
array(60, 'm'),
array(1, 's')
);
for ($i = 0, $n = count($timeUnits); $i < $n; $i++) {
$seconds = $timeUnits[$i][0];
$unit = $timeUnits[$i][1];
if (($count = floor($since / $seconds)) != 0) {
break;
}
}
return "$count{$unit}";
# If it's been a day or more, return the date: day (without leading 0) and 3-letter month
} else {
return date('j M', strtotime($dateStr));
}
}
//-------------------------------------------------------------- Format the tweet text (links, hashtags, mentions)
function formatTweet($tweet) {
$linkified = '@(https?://([-\w\.]+[-\w])+(:\d+)?(/([\w/_\.#-]*(\?\S+)?[^\.\s])?)?)@';
$hashified = '/(^|[\n\s])#([^\s"\t\n\r<:]*)/is';
$mentionified = '/(^|[\n\s])@([^\s"\t\n\r<:]*)/is';
$prettyTweet = preg_replace(
array(
$linkified,
$hashified,
$mentionified
),
array(
'<a href="$1" class="link-tweet" target="_blank">$1</a>',
'$1<a class="link-hashtag" href="https://twitter.com/search?q=%23$2&src=hash" target="_blank">#$2</a>',
'$1<a class="link-mention" href="http://twitter.com/$2" target="_blank">@$2</a>'
),
$tweet
);
return $prettyTweet;
}
//-------------------------------------------------------------- Timeline HTML output
# This output markup adheres to the Twitter developer display requirements (https://dev.twitter.com/terms/display-requirements)
# Open the timeline list
echo '<ul id="tweet-list" class="tweet-list">';
# The tweets loop
foreach ($twitter_data as $tweet) {
$retweet = $tweet['retweeted_status'];
$isRetweet = !empty($retweet);
# Retweet - get the retweeter's name and screen name
$retweetingUser = $isRetweet ? $tweet['user']['name'] : null;
$retweetingUserScreenName = $isRetweet ? $tweet['user']['screen_name'] : null;
# Tweet source user (could be a retweeted user and not the owner of the timeline)
$user = !$isRetweet ? $tweet['user'] : $retweet['user'];
$userName = $user['name'];
$userScreenName = $user['screen_name'];
$userAvatarURL = stripcslashes($user['profile_image_url']);
$userAccountURL = 'http://twitter.com/' . $userScreenName;
# The tweet
$id = number_format($tweet['id'], 0, '.', '');
$formattedTweet = !$isRetweet ? formatTweet($tweet['text']) : formatTweet($retweet['text']);
$statusURL = 'http://twitter.com/' . $userScreenName . '/status/' . $id;
$date = timeAgo($tweet['created_at']);
# Reply
$replyID = number_format($tweet['in_reply_to_status_id'], 0, '.', '');
$isReply = !empty($replyID);
# Tweet actions (uses web intents)
$replyURL = 'https://twitter.com/intent/tweet?in_reply_to=' . $id;
$retweetURL = 'https://twitter.com/intent/retweet?tweet_id=' . $id;
$favoriteURL = 'https://twitter.com/intent/favorite?tweet_id=' . $id;
?>
<li id="<?php echo 'tweetid-' . $id; ?>" class="tweet<?php
if ($isRetweet) echo ' is-retweet';
if ($isReply) echo ' is-reply';
if ($tweet['retweeted']) echo ' visitor-retweeted';
if ($tweet['favorited']) echo ' visitor-favorited'; ?>">
<div class="tweet-info">
<div class="user-info">
<a class="user-avatar-link" href="<?php echo $userAccountURL; ?>">
<img class="user-avatar" src="<?php echo $userAvatarURL; ?>">
</a>
<p class="user-account">
<a class="user-name" href="<?php echo $userAccountURL; ?>"><strong><?php echo $userName; ?></strong></a>
<a class="user-screenName" href="<?php echo $userAccountURL; ?>">@<?php echo $userScreenName; ?></a>
</p>
</div>
<a class="tweet-date permalink-status" href="<?php echo $statusURL; ?>" target="_blank">
<?php echo $date; ?>
</a>
</div>
<blockquote class="tweet-text">
<?php
echo '<p>' . $formattedTweet . '</p>';
echo '<p class="tweet-details">';
if ($isReply) {
echo '
<a class="link-reply-to permalink-status" href="http://twitter.com/' . $tweet['in_reply_to_screen_name'] . '/status/' . $replyID . '">
In reply to...
</a>
';
}
if ($isRetweet) {
echo '
<span class="retweeter">
Retweeted by <a class="link-retweeter" href="http://twitter.com/' . $retweetingUserScreenName . '">' .
$retweetingUser
. '</a>
</span>
';
}
echo '<a class="link-details permalink-status" href="' . $statusURL . '" target="_blank">Details</a></p>';
?>
</blockquote>
<div class="tweet-actions">
<a class="action-reply" href="<?php echo $replyURL; ?>">Reply</a>
<a class="action-retweet" href="<?php echo $retweetURL; ?>">Retweet</a>
<a class="action-favorite" href="<?php echo $favoriteURL; ?>">Favorite</a>
</div>
</li>
<?php
} # End tweets loop
# Close the timeline list
echo '</ul>';
# echo $json; // Uncomment this line to view the entire JSON array. Helpful: http://www.freeformatter.com/json-formatter.html
?>

20
includes/config.php Executable file
View File

@ -0,0 +1,20 @@
<?php
ob_start(); //Turns on output buffering
session_start();
date_default_timezone_set("Asia/Bangkok");
// attempt to connect to the database via PDO
$servername = "localhost";
$username = "posts";
$password = "XL8YkuMhUncCG3SYs2725KQBaETHvLtnJDg9AE3kVAQe27wxmegyDKHBf3sSmu54yLzNknC2ynsrjRDW2RWXrXqUFh8em9pzBXYVMPg48KFQ6kMuMvj5bNTUpSPkx3zN";
try {
$con = new PDO("mysql:host=$servername;dbname=blogs", $username, $password);
// set the PDO error mode to exception
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
echo "Connection failed: " . $e->getMessage();
}
header('Content-Type: text/html; charset=utf-8');
?>

6
includes/footer.php Executable file
View File

@ -0,0 +1,6 @@
</body>
</html>
<?php
mysqli_close($conn);
?>

78
includes/header.php Executable file
View File

@ -0,0 +1,78 @@
<?php
include("config.php");
include("classes/Markdown.php");
include("classes/Post.php");
$motd = array(
"Don't worry, be happy.",
"This website does not have any JavaScript. Believe Me. ",
"¯\_(ツ)_/¯",
"This is definitely not an MOTD.",
"Main website: <a href='https://winsdominoes.net'>https://winsdominoes.net</a>",
"y'know what's epic? getting yo s*** done after many months",
"Cook rice in a rice cooker, please. ",
"Solar energy is cool. This website is being powered by Solar!",
"We're no strangers to love", "You know the rules and so do I", "A full commitment's what I'm thinking of", "You wouldn't get this from any other guy", "I just wanna tell you how I'm feeling", "Gotta make you understand", "Never gonna give you up", "Never gonna let you down", "Never gonna run around and desert you", "Never gonna make you cry", "Never gonna say goodbye", "Never gonna tell a lie and hurt you", "We've known each other for so long", "Your heart's been aching but you're too shy to say it", "Inside we both know what's been going on", "We know the game and we're gonna play it", "And if you ask me how I'm feeling", "Don't tell me you're too blind to see", "Never gonna give you up", "Never gonna let you down", "Never gonna run around and desert you", "Never gonna make you cry", "Never gonna say goodbye", "Never gonna tell a lie and hurt you", "Never gonna give you up", "Never gonna let you down", "Never gonna run around and desert you", "Never gonna make you cry", "Never gonna say goodbye", "Never gonna tell a lie and hurt you", "Never gonna give, never gonna give", "We've known each other for so long", "Your heart's been aching but you're too shy to say it", "Inside we both know what's been going on", "We know the game and we're gonna play it", "I just wanna tell you how I'm feeling", "Gotta make you understand", "Never gonna give you up", "Never gonna let you down", "Never gonna run around and desert you", "Never gonna make you cry", "Never gonna say goodbye", "Never gonna tell a lie and hurt you", "Never gonna give you up", "Never gonna let you down", "Never gonna run around and desert you", "Never gonna make you cry", "Never gonna say goodbye", "Never gonna tell a lie and hurt you", "Never gonna give you up", "Never gonna let you down", "Never gonna run around and desert you", "Never gonna make you cry", "Never gonna say goodbye",
"You definitely didn't get rickrolled on this website. ",
"Incandescent or LED? Hmmmmmmm"
);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Win's Posts - The homepage of Win's Life</title>
<meta name="title" content="Win's Personal Feed">
<meta name="description" content="A website by Win. ">
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website">
<meta property="og:url" content="https://posts.winsdominoes.net/">
<meta property="og:title" content="Win's Personal Feed">
<meta property="og:description" content="A website by Win.">
<!-- Twitter -->
<meta property="twitter:card" content="summary_large_image">
<meta property="twitter:url" content="https://posts.winsdominoes.net/">
<meta property="twitter:title" content="Win's Personal Feed">
<meta property="twitter:description" content="A personal website">
<!-- bootstrap -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
<!-- my custom css files-->
<link rel="stylesheet" href="assets/css/style.css">
<!-- twitter css and js -->
<link rel="stylesheet" href="assets/css/twitter.css">
<script src="assets/js/twitter.js"></script>
</head>
<style>
body {
font-family: "Arial"
}
img {
width: 100%;
}
</style>
<body>
<header class="container header">
<br>
<a href="index.php"><h1><u>Win's Personal Stories</u></h1></a>
<!-- <marquee direction="right" behavior="alternate"><i><u><?php echo $motd[rand(0, count($motd) - 1)]; ?></u></i></marquee> -->
<span>Salvēte, omnēs! This website is hosted on a <a href="https://bulb.winscloud.net">Raspberry Pi 4B!</a></span>
<div id="hideShow" style="display: none;">
<img src="assets/images/pi.jpg" alt="Pi" width="100%" >
</div>
</header>

70
includes/postHeader.php Executable file
View File

@ -0,0 +1,70 @@
<?php
include("config.php");
include("classes/Markdown.php");
include("classes/Post.php");
include("classes/Comment.php");
$postUrl = htmlspecialchars(strip_tags($_GET["url"], ENT_QUOTES));
$Parsedown = new Parsedown();
// check if posturl exists
if(!$postUrl) {
exit("That post does not exist.");
}
$post = new Post($con, $postUrl);
$postUrl = $post->getPostUrl();
$postAuthor = $post->getPostAuthor();
$postPublishedDate = $post->getPublishedDate();
//$postContent = $Parsedown->text($post->getPostContent());
$postContent = $post->getPostContent();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Win on Win's Feed: "<?php echo $postContent ?>"</title>
<meta name="title" content="Win @<?php echo $postAuthor . " · " . $postPublishedDate ?>">
<meta name="description" content="<?php echo $postContent; ?>">
<meta name="theme-color" content="#22b14c">
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website">
<meta property="og:site_name" content="Win's Personal Feed">
<meta property="og:url" content="https://posts.winsdominoes.net/status.php?url=<?php echo $postUrl ?>">
<meta property="og:title" content="Win (@<?php echo $postAuthor . ") · " . $postPublishedDate ?>">
<meta property="og:description" content="<?php echo $postContent; ?>">
<!-- Twitter -->
<meta property="twitter:card" content="summary_large_image">
<meta property="twitter:url" content="https://posts.winsdominoes.net/status.php?url=<?php echo $postUrl ?>">
<meta property="twitter:title" content="Win @<?php echo $postAuthor . " · " . $postPublishedDate ?>">
<meta property="twitter:description" content="<?php echo $postContent; ?>">
<!-- bootstrap -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
<!-- my custom css files-->
<link rel="stylesheet" href="assets/css/style.css">
<!-- twitter css and js -->
<link rel="stylesheet" href="assets/css/twitter.css">
<script src="assets/js/twitter.js"></script>
</head>
<body>
<header>
<div class="container header">
<br>
<a href="index.php"><h1><u>Win's Personal Posts</u></h1></a>
<hr>
</div>
</header>

58
index.php Executable file
View File

@ -0,0 +1,58 @@
<?php
include("includes/header.php");
$orderByGet = $_GET["orderBy"] ?? "latest";
if($orderByGet == "oldest") {
$orderBy = "ASC";
} else if ($orderByGet == "latest") {
$orderBy = "DESC";
} else {
$orderBy = "DESC";
}
$offset = isset($_GET["offset"]) ? $_GET['offset'] : 0;
$Parsedown = new Parsedown();
?>
<div class="container">
<div class="row">
<div class="leftSection col">
<b>Order by: <a href="index.php?orderBy=latest" class="link-secondary" style="color: lightblue;">latest</a> | <a href="index.php?orderBy=oldest" class="link-secondary" style="color: lightblue;">oldest</a> || </b><a href="https://posts.winsdominoes.net/feed.php" style="color: orange;">Get RSS Feed!</a>
<hr>
<?php
$stmt = $con->prepare("SELECT * FROM posts ORDER BY id $orderBy");
$stmt->execute();
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$post = new Post($con, $row);
$postUrl = $post->getPostUrl();
$postAuthor = $post->getPostAuthor();
$postedDate = $post->getPublishedDate();
$postContent = $Parsedown->text($post->getPostContent());
$item = "<div class='post' style='padding: 10px; border: 1px solid rgb(47, 51, 54); border-radius: 0px; margin-bottom: 5px;'>
<span id='content' style='font-size: 12px;'>" . $postAuthor . " · <span style='color: gray'>" . $postedDate . " [GMT +7]</span></span>
<p class='post-text'>" . $postContent . "</p>
<a href='status.php?url=$postUrl' class='text-decoration-none' style='font-size: 12px;'>Read More</a>
</div>";
echo $item;
}
?>
</div>
<!-- <div class="rightSection col">
<b>Tweets <a href="https://twitter.com/WinsDominoes">@WinsDominoes on Twitter</a></b>
<hr>
<?php
include_once('includes/classes/twitter.php');
?>
</div> -->
</div>
</div>
<?php
include("includes/footer.php");
?>

26
status.php Executable file
View File

@ -0,0 +1,26 @@
<?php
include("includes/postHeader.php");
?>
<div class="container">
<div style="padding: 10px; border: 1px solid rgb(47, 51, 54); border-radius: 0px;">
<div class="card-body">
<div class="card-title">
<span><b>Win</b></span>
</div>
<h6 class="card-subtitle mb-2 text-muted" style="margin: 5px 5px 5px 0px">
<?php echo $postPublishedDate ?> GMT +7
</h6>
<p><?php echo $Parsedown->text($post->getPostContent()); ?></p>
</div>
</div>
<br>
</div>
<?php
include("includes/footer.php");
?>

50
submit/addComment.php Executable file
View File

@ -0,0 +1,50 @@
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
include_once("../includes/config.php");
function generateRandomString($length = 11) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
$commentUrlGen = generateRandomString();
// check if request is post
if(isset($_POST["commentSubmitButton"])) {
$postUrl = htmlspecialchars(strip_tags($_POST["postUrl"], ENT_QUOTES));
$author = htmlspecialchars(strip_tags($_POST["commentAuthor"], ENT_QUOTES));
$commentContent = htmlspecialchars(strip_tags($_POST["commentText"], ENT_QUOTES));
// check if comment content is empty
if($commentContent == "") {
echo "<p>Your comment is empty.</p>";
}
else {
if(!$author) {
$author = "Anonymous";
}
// insert comment into database
$query = $con->prepare("INSERT INTO comments(comment_url, comment_author, comment_body, comment_onPost) VALUES(:commentUrl, :commentAuthor, :commentContent, :commentOnPost)");
$query->bindParam(":commentUrl", $commentUrlGen);
$query->bindParam(":commentContent", $commentContent);
$query->bindParam(":commentAuthor", $author);
$query->bindParam(":commentOnPost", $postUrl);
$query->execute();
// redirect to post page
header("Location: ../status.php?url=$postUrl");
}
} else {
echo "<p>This is not a post request</p>";
}
?>