コミットを比較

..

26 コミット

作成者 SHA1 メッセージ 日付
守矢諏訪子 81b8b6359e GPL → ISC 2024-05-28 19:22:36 +09:00
守矢諏訪子 bd0e2e2d0a Merge branch 'master' of gitler.moe:suwako/spliti 2024-03-31 13:35:00 +09:00
守矢諏訪子 a406479189 2.2.0 2024-03-31 13:34:45 +09:00
守矢諏訪子 594eab89d5 GNU Make → BSD Make 2024-03-31 12:37:36 +09:00
守矢諏訪子 7f646dd8a8 ごめん 2024-03-31 12:25:20 +09:00
守矢諏訪子 ac2ddda27e . 2024-02-24 03:14:33 +09:00
守矢諏訪子 13a283d75f ちんこ 2023-11-30 10:04:04 +09:00
守矢諏訪子 59aa57f4bc 2.1.0 2023-11-15 00:38:15 +09:00
守矢諏訪子 bb8e434000 つぶやきを見るページ(list_quote.pl)を追加 2023-11-15 00:38:04 +09:00
守矢諏訪子 c7063f75c3 「bypass_stats」リンクを削除 2023-11-13 17:16:05 +09:00
守矢諏訪子 1750418646 ファイルを分けた方が良いかしら… 2023-11-13 16:52:46 +09:00
守矢諏訪子 b81c1c0ae8 カテゴリーのページネーション 2023-11-13 16:46:21 +09:00
守矢諏訪子 a5aeb32f19 出版社ページのページネーション 2023-11-13 16:02:01 +09:00
守矢諏訪子 5374096c8a 出版社ページを追加 2023-11-13 15:58:02 +09:00
守矢諏訪子 7534554e7f 2.0.1 2023-11-06 16:16:43 +09:00
守矢諏訪子 498f565071 ごめん 2023-11-05 03:14:41 +09:00
守矢諏訪子 8757596fc2 PHPからGo言語に交換しました 2023-11-05 03:12:44 +09:00
守矢諏訪子 2e9f24b992 1.1.2 2023-10-23 15:05:55 +09:00
守矢諏訪子 eeba0ae9d8 spliti 1.1.1 2023-09-09 21:43:01 +09:00
守矢諏訪子 1609cde8b8 ごめん 2023-09-09 21:30:13 +09:00
守矢諏訪子 83f61a90f5 インスタンス 2023-05-31 11:45:49 +09:00
守矢諏訪子 6ca5ee9452 変更ログ 2023-05-24 12:18:29 +09:00
守矢諏訪子 79e1da84b7 掃除 2023-05-24 12:14:42 +09:00
守矢諏訪子 6abb57ee01 カテゴリーの追加 2023-05-24 12:14:11 +09:00
守矢諏訪子 1e73a7ae63 コンフィグ化 2023-05-24 09:44:17 +09:00
守矢諏訪子 317b1ff04e 画像プロクシー 2023-05-24 09:41:56 +09:00
31個のファイルの変更1178行の追加245行の削除

4
.gitignore vendored
ファイルの表示

@ -1 +1,3 @@
/config.php /spliti
/bin
/*.tar.gz

39
CHANGELOG.md ノーマルファイル
ファイルの表示

@ -0,0 +1,39 @@
# 2.3.0
* GPL → ISC
# 2.2.0
* GNU MakeからBSD Makeに変更
* 社会、トレンド、地域、海外、コラム、及びライフスタイルのカテゴリページの修正
* マウスオーバーのハイライトの追加
* .pageList02のスタイリングの追加
# 2.1.0
* 出版社ページを追加
* 出版社ページのページネーション
* カテゴリーのページネーション
* つぶやきを見るページ(list_quote.pl)を追加
# 2.0.1
* manページを修正
* 「-h」を修正
* エラーページを修正
# 2.0.0
* PHPからGo言語に交換しました
# 1.1.2
* 投稿内の画像もプロクシー化
* 投稿内の画像はレスポンシブに
# 1.1.1
* YouTube動画があれば、オワコンYouTubeに変更させる様に
* サムネイルがなければ、getimg()関数をす部に終了する様に
* もっと小さいバグを修正
# 1.1.0
* 画像はimgproxy化
* カテゴリーを追加
* ホームページを追加(普通Mixiにアクセスするのは不要になった)
# 1.0.0
* 最初リリース

14
LICENSE.txt ノーマルファイル
ファイルの表示

@ -0,0 +1,14 @@
Copyright © 2004-2011 by Internet Systems Consortium, Inc. ("ISC")
Copyright © 2018-2024 by 076.moe
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.

69
Makefile ノーマルファイル
ファイルの表示

@ -0,0 +1,69 @@
NAME!=cat main.go | grep "var sofname" | awk '{print $$4}' | sed "s/\"//g"
VERSION!=cat main.go | grep "var version" | awk '{print $$4}' | sed "s/\"//g"
# Linux、Haiku、Illumos = /usr、FreeBSDとOpenBSD = /usr/local、NetBSD = /usr/pkg
PREFIX=/usr/local
MANPREFIX=${PREFIX}/share/man
# FreeBSD = /usr/local/etc、NetBSD = /usr/pkg/etc、それ以外 = /etc
CNFPREFIX?=/etc
CC=CGO_ENABLED=0 go build
# リリース。なし=デバッグ。
RELEASE=-ldflags="-s -w" -buildvcs=false
all:
${CC} ${RELEASE} -o ${NAME}
release:
env GOOS=linux GOARCH=amd64 ${CC} ${RELEASE} -o bin/${NAME}-${VERSION}-linux-amd64
env GOOS=linux GOARCH=arm64 ${CC} ${RELEASE} -o bin/${NAME}-${VERSION}-linux-arm64
env GOOS=linux GOARCH=arm ${CC} ${RELEASE} -o bin/${NAME}-${VERSION}-linux-arm
env GOOS=linux GOARCH=riscv64 ${CC} ${RELEASE} -o bin/${NAME}-${VERSION}-linux-riscv64
env GOOS=linux GOARCH=386 ${CC} ${RELEASE} -o bin/${NAME}-${VERSION}-linux-386
env GOOS=linux GOARCH=ppc64 ${CC} ${RELEASE} -o bin/${NAME}-${VERSION}-linux-ppc64
env GOOS=linux GOARCH=mips64 ${CC} ${RELEASE} -o bin/${NAME}-${VERSION}-linux-mips64
env GOOS=openbsd GOARCH=amd64 ${CC} ${RELEASE} -o bin/${NAME}-${VERSION}-openbsd-amd64
env GOOS=openbsd GOARCH=386 ${CC} ${RELEASE} -o bin/${NAME}-${VERSION}-openbsd-386
env GOOS=openbsd GOARCH=arm64 ${CC} ${RELEASE} -o bin/${NAME}-${VERSION}-openbsd-arm64
env GOOS=openbsd GOARCH=arm ${CC} ${RELEASE} -o bin/${NAME}-${VERSION}-openbsd-arm
env GOOS=openbsd GOARCH=mips64 ${CC} ${RELEASE} -o bin/${NAME}-${VERSION}-openbsd-mips64
env GOOS=freebsd GOARCH=amd64 ${CC} ${RELEASE} -o bin/${NAME}-${VERSION}-freebsd-amd64
env GOOS=freebsd GOARCH=386 ${CC} ${RELEASE} -o bin/${NAME}-${VERSION}-freebsd-386
env GOOS=freebsd GOARCH=arm ${CC} ${RELEASE} -o bin/${NAME}-${VERSION}-freebsd-arm4
env GOOS=freebsd GOARCH=arm64 ${CC} ${RELEASE} -o bin/${NAME}-${VERSION}-freebsd-arm64
env GOOS=freebsd GOARCH=riscv64 ${CC} ${RELEASE} -o bin/${NAME}-${VERSION}-freebsd-riscv64
env GOOS=netbsd GOARCH=amd64 ${CC} ${RELEASE} -o bin/${NAME}-${VERSION}-netbsd-amd64
env GOOS=netbsd GOARCH=386 ${CC} ${RELEASE} -o bin/${NAME}-${VERSION}-netbsd-386
env GOOS=netbsd GOARCH=arm ${CC} ${RELEASE} -o bin/${NAME}-${VERSION}-netbsd-arm4
env GOOS=netbsd GOARCH=arm64 ${CC} ${RELEASE} -o bin/${NAME}-${VERSION}-netbsd-arm64
env GOOS=illumos GOARCH=amd64 ${CC} ${RELEASE} -o bin/${NAME}-${VERSION}-illumos-amd64
clean:
rm -f ${NAME} ${NAME}-${VERSION}.tar.gz
dist: clean
mkdir -p ${NAME}-${VERSION}
cp -R LICENSE.txt Makefile README.md CHANGELOG.md\
view static logo.jpg\
${NAME}.1 *.go *.json go.mod go.sum ${NAME}-${VERSION}
tar zcfv ${NAME}-${VERSION}.tar.gz ${NAME}-${VERSION}
rm -rf ${NAME}-${VERSION}
config:
mkdir -p ${DESTDIR}${CNFPREFIX}/spliti
cp config.json ${DESTDIR}${CNFPREFIX}/spliti
install: all
mkdir -p ${DESTDIR}${PREFIX}/bin
cp -f ${NAME} ${DESTDIR}${PREFIX}/bin
chmod 755 ${DESTDIR}${PREFIX}/bin/${NAME}
mkdir -p ${DESTDIR}${MANPREFIX}/man1
sed "s/VERSION/${VERSION}/g" < ${NAME}.1 > ${DESTDIR}${MANPREFIX}/man1/${NAME}.1
chmod 644 ${DESTDIR}${MANPREFIX}/man1/${NAME}.1
mkdir -p ${DESTDIR}${CNFPREFIX}/${NAME}
chmod 755 ${DESTDIR}${CNFPREFIX}/${NAME}
uninstall:
rm -f ${DESTDIOR}${PREFIX}/bin/${NAME}\
${DESTDIR}${MANPREFIX}/man1/${NAME}.1\
${DESTDIR}${CNFPREFIX}/${NAME}
.PHONY: all release clean dist config install uninstall

ファイルの表示

@ -10,30 +10,76 @@ mixi向けプライバシーUI。
$domain="example.com" $domain="example.com"
cd /var/www/htdocs cd /var/www/htdocs
git clone https://gitler.moe/suwako/spliti.git && cd spliti git clone https://gitler.moe/suwako/spliti.git && cd spliti
mv config.example.php config.php find . -type f -name "config.json" -exec sed -i 's/mixi.076.moe/$domain/g'
find . -type f -name "config.php" -exec sed -i 's/mixi.owacon.moe/$domain/g' ```
### OpenBSD(オススメ)
```sh
make
doas make install
doas make config
cd /etc
wget https://076.moe/repo/webserver/relayd/spliti.conf
mv spliti.conf relayd.conf
find . -type f -name "/etc/relayd.conf" -exec sed -i 's/DOMAIN/$domain/g'
rcctl restart relayd
``` ```
### Linux ### Linux
**注意BSD Makeをインストールして下さい。GNU Makeは未対応です。**
```sh ```sh
cp srv/nginx.conf /etc/nginx/sites-enabled/spliti.conf bmake
find . -type f -name "/etc/nginx/sites-enabled/spliti.conf" -exec sed -i 's/ドメイン名/$domain/g' doas bmake install PREFIX=/usr
doas bmake config
cp /etc/nginx/sites-enabled
wget https://076.moe/repo/webserver/nginx/spliti.conf
find . -type f -name "/etc/nginx/sites-enabled/spliti.conf" -exec sed -i 's/DOMAIN/$domain/g'
/etc/init.d/nginx restart /etc/init.d/nginx restart
``` ```
### FreeBSD ### FreeBSD
```sh ```sh
make
doas make install
doas make config CNFPREFIX=/usr/local/etc
cp srv/nginx.conf /usr/local/etc/nginx/sites-enabled/spliti.conf cp srv/nginx.conf /usr/local/etc/nginx/sites-enabled/spliti.conf
find . -type f -name "/usr/local/etc/nginx/sites-enabled/spliti.conf" -exec sed -i 's/ドメイン名/$domain/g' wget https://076.moe/repo/webserver/nginx/spliti.conf
find . -type f -name "/usr/local/etc/nginx/sites-enabled/spliti.conf" -exec sed -i 's/DOMAIN/$domain/g'
service nginx restart service nginx restart
``` ```
### OpenBSD ### NetBSD
```sh ```sh
cat /etc/httpd.conf srv/httpd.conf > /etc/httpd.conf make
find . -type f -name "/etc/httpd.conf" -exec sed -i 's/ドメイン名/$domain/g' doas make install
rcctl restart httpd doas make config CNFPREFIX=/usr/pkg/etc
cp srv/nginx.conf /usr/pkg/etc/nginx/sites-enabled/spliti.conf
wget https://076.moe/repo/webserver/nginx/spliti.conf
find . -type f -name "/usr/pkg/etc/nginx/sites-enabled/spliti.conf" -exec sed -i 's/DOMAIN/$domain/g'
service nginx restart
``` ```
## インスタンス一覧
### 一般ネット
| ウエブサイト | [クラフレ](http://jezf25zgvxlsvuzdzm6fg2hoetmruhy4uxnolyw46tuh4jugcwc7byqd.onion/Cloudflare%E3%82%92%E4%BD%BF%E3%82%8F%E3%81%AA%E3%81%84%E7%90%86%E7%94%B1%EF%BC%88%E3%83%AA%E3%83%81%E3%83%A3%E3%83%BC%E3%83%89%E3%83%BB%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%83%9E%E3%83%B3%EF%BC%89) | 注 |
| -- | -- | -- |
| [https://mixi.076.moe/](https://mixi.076.moe/) | 無 | 公式インスタンス |
### Tor
| オニオン | 注 |
| -- | -- |
| | |
### I2P
| イープサイト | 注 |
| -- | -- |
| | |

64
check.go ノーマルファイル
ファイルの表示

@ -0,0 +1,64 @@
package main
import (
"strings"
"net/url"
"fmt"
)
func getid(u string) (string, error) {
parse, err := url.Parse(u)
if err != nil {
return "", err
}
params, err := url.ParseQuery(parse.RawQuery)
if err != nil {
return "", err
}
id, ok := params["id"]
if !ok || len(id) == 0 {
return "", fmt.Errorf("IDを見つけられませんでした。")
}
return id[0], nil
}
/* 記事かの確認 */
func isarticle(u string) bool {
chk := strings.Split(u, "=")
return len(chk) > 2 &&
(chk[0] == "/view_news.pl?id" || chk[0] == "/view_news.pl?from" || chk[0] == "/view_news.pl?media_id" || chk[0] == "/view_news.pl?stkt")
}
/* 部分圏かの確認 */
func issubcat(u string) bool {
chk := strings.Split(u, "=")
return len(chk) > 1 &&
(chk[0] == "/list_news_category.pl?id" || chk[0] == "/list_news_category.pl?page" || chk[0] == "/list_news_category.pl?sort" || chk[0] == "/list_news_category.pl?type" || chk[0] == "/list_news_category.pl?sub_category_id") &&
strings.Contains(u, "type=bn")
}
/* 部分かの確認 */
func iscategory(u string) bool {
chk := strings.Split(u, "=")
return len(chk) > 1 &&
(chk[0] == "/list_news_category.pl?id" || chk[0] == "/list_news_category.pl?sub_category_id" || chk[0] == "/list_news_category?from") &&
!strings.Contains(u, "type=bn")
}
/* 出版社かの確認 */
func ispublish(u string) bool {
chk := strings.Split(u, "=")
return len(chk) > 1 && (chk[0] == "/list_news_media.pl?id" || chk[0] == "/list_news_media.pl?page")
}
/* つぶやきかの確認 */
func istubayaki(u string) bool {
chk := strings.Split(u, "=")
return len(chk) > 1 &&
(chk[0] == "/list_quote.pl?id" || chk[0] == "/list_quote.pl?type" || chk[0] == "/list_quote.pl?sort" || chk[0] == "/list_quote.pl?news_id") &&
strings.Contains(u, "type=voice") &&
(strings.Contains(u, "sort=post_time") || strings.Contains(u, "sort=feedback_count"))
}

ファイルの表示

@ -1,3 +0,0 @@
<?php
define("DOMAIN", "https://mixi.owacon.moe");
?>

66
config.go ノーマルファイル
ファイルの表示

@ -0,0 +1,66 @@
package main
import (
"fmt"
"encoding/json"
"io/ioutil"
"runtime"
"os"
"errors"
"strings"
)
type Config struct {
configpath, webpath, domain, imgproxy, ip string
}
func getconf () (Config, error) {
var cnf Config
prefix := "/usr"
if runtime.GOOS == "freebsd" || runtime.GOOS == "openbsd" {
prefix += "/local"
} else if runtime.GOOS == "netbsd" {
prefix += "/pkg"
}
cnf.configpath = "/etc/spliti/config.json"
if runtime.GOOS == "freebsd" || runtime.GOOS == "netbsd" {
cnf.configpath = prefix + cnf.configpath
}
data, err := ioutil.ReadFile(cnf.configpath)
if err != nil {
fmt.Println("config.jsonを開けられません: ", err)
return cnf, errors.New("コンフィグファイルは " + cnf.configpath + " に創作して下さい。")
}
var payload map[string]interface{}
json.Unmarshal(data, &payload)
if payload["webpath"] == nil {
payload["webpath"] = "/var/www/htdocs/spliti"
}
if payload["domain"] == nil {
return cnf, errors.New("「domain」の値が設置していません。")
}
if payload["imgproxy"] == nil {
payload["imgproxy"] = "https://imgproxy.076.moe"
}
if payload["ip"] == nil {
payload["ip"] = "0.0.0.0"
}
if _, err := os.Stat(payload["webpath"].(string)); err != nil {
fmt.Printf("%v\n", err)
return cnf, errors.New("mkdirコマンドを使って、 " + payload["webpath"].(string))
}
if !strings.HasPrefix(payload["domain"].(string), "http://") && !strings.HasPrefix(payload["domain"].(string), "https://") {
return cnf, errors.New("URLは「http://」又は「https://」で始める様にして下さい。")
}
cnf.webpath = payload["webpath"].(string)
cnf.domain = payload["domain"].(string)
cnf.imgproxy = payload["imgproxy"].(string)
cnf.ip = payload["ip"].(string)
payload = nil
return cnf, nil
}

6
config.json ノーマルファイル
ファイルの表示

@ -0,0 +1,6 @@
{
"domain": "https://mixi.076.moe",
"webpath": "/var/www/htdocs/spliti",
"imgproxy": "https://imgproxy.076.moe",
"ip": "0.0.0.0"
}

8
go.mod ノーマルファイル
ファイルの表示

@ -0,0 +1,8 @@
module spliti
go 1.20
require (
golang.org/x/net v0.17.0
golang.org/x/text v0.14.0
)

4
go.sum ノーマルファイル
ファイルの表示

@ -0,0 +1,4 @@
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=

44
lib.go ノーマルファイル
ファイルの表示

@ -0,0 +1,44 @@
package main
import (
"io"
"strings"
"bytes"
"golang.org/x/net/html"
"golang.org/x/text/encoding/japanese"
"golang.org/x/text/transform"
)
/* PHPであるstrip_tagsはGo言語で存在しないから、自分で作る */
func strip_tags(data string) string {
doc, err := html.Parse(strings.NewReader(data))
if err != nil {
panic("HTMLをパーシングに失敗。")
}
var buf bytes.Buffer
var f func(*html.Node)
f = func(n *html.Node) {
if n.Type == html.TextNode {
buf.WriteString(n.Data)
}
for c := n.FirstChild; c != nil; c = c.NextSibling {
f(c)
}
}
f(doc)
return buf.String()
}
func EUCJPToUTF8(input []byte) (string, error) {
transformer := japanese.EUCJP.NewDecoder()
reader := transform.NewReader(bytes.NewReader(input), transformer)
result, err := io.ReadAll(reader)
if err != nil {
return "エンコーディングに失敗", err
}
return string(result), nil
}

バイナリ
logo.jpg ノーマルファイル

バイナリファイルは表示されません。

変更後

幅:  |  高さ:  |  サイズ: 13 KiB

52
main.go ノーマルファイル
ファイルの表示

@ -0,0 +1,52 @@
package main
import (
"fmt"
"os"
"strconv"
)
var sofname = "spliti"
var version = "2.3.0"
func help() {
fmt.Println(" " + sofname + "-" + version + " - mixi向けプライバシーUI")
fmt.Println("https://mixi.076.moe/ | https://gitler.moe/suwako/spliti")
fmt.Println("")
fmt.Println("使い方:")
fmt.Println(sofname + " -v :バージョンを表示")
fmt.Println(sofname + " -s [ポート番号] ポート番号でウエブサーバーを実行(デフォルト9930)")
fmt.Println(sofname + " -h :ヘルプを表示")
}
func main() {
cnf, err := getconf()
if err != nil {
fmt.Println(err)
return
}
args := os.Args
if len(args) == 3 && args[1] == "-s" {
if port, err := strconv.Atoi(args[2]); err != nil {
fmt.Printf("%qは数字ではありません。\n", args[2])
return
} else {
serv(cnf, port)
return
}
} else if len(args) == 2 {
if args[1] == "-v" {
fmt.Println(sofname + "-" + version)
} else if args[1] == "-s" {
serv(cnf, 9930)
} else {
help()
return
}
} else {
help()
return
}
}

115
page.go ノーマルファイル
ファイルの表示

@ -0,0 +1,115 @@
package main
import (
"fmt"
"io"
"net/http"
"regexp"
"strings"
)
/* ページのタイトル */
func gettitle(str string) string {
re := regexp.MustCompile("<title>(.*)</title>")
matches := re.FindStringSubmatch(str)
if len(matches) > 1 {
return matches[1]
}
return ""
}
func getimg(str string, cnf Config) string {
re := regexp.MustCompile(`<img class="NEWS_tempPhoto__picture" src="(.*)" alt="">`)
matches := re.FindStringSubmatch(str)
if len(matches) > 1 {
return strings.Replace(matches[1], "https://", cnf.imgproxy+"/", -1)
}
return ""
}
func getdesc(str string) string {
re := regexp.MustCompile(`<div class="newsArticle">(.*?)</div>`)
res := re.ReplaceAllString(str, "")
return strip_tags(res)
}
/* 記事の受取 */
func get(url string, cnf Config) map[string]string {
// デフォルト=エラー
res := make(map[string]string)
res["title"] = "見つけられない"
res["content"] = `
<div class="newsArticle"><div class="articleHeading02">
<div class="headingArea">
<h1>見つけられなかった</h1>
</div>
</div>
<div class="contents clearfix">
<div class="article decoratable">
<p>ごめんね</p>
</div>
</div>
`
res["img"] = ""
res["desc"] = ""
res["err"] = ""
resp, err := http.Get("https://news.mixi.jp" + url)
if err != nil {
res["err"] = "URLエラー"
fmt.Println(res["err"] + ": " + err.Error())
return res
}
defer resp.Body.Close()
if resp.StatusCode == http.StatusOK {
bytebody, err := io.ReadAll(resp.Body)
if err != nil {
res["err"] = "内容はバイトコードとして読み込みに失敗。"
fmt.Println(res["err"])
return res
}
body, err := EUCJPToUTF8(bytebody)
if err != nil {
res["err"] = err.Error()
fmt.Println(res["err"])
return res
}
id, _ := getid(url)
res["title"] = gettitle(body)
if isarticle(url) {
if !strings.Contains(body, "newsArticle") {
res["content"] = rmebloat(body, cnf)
} else {
res["img"] = getimg(body, cnf)
res["content"] = rmbloat(id, body, cnf)
}
} else if ispublish(url) {
res["content"] = rmpbloat(body, cnf)
} else if issubcat(url) {
if strings.Contains(body, `<p class="messageAlert">存在しないカテゴリです</p>`) {
res["content"] = rmebloat(body, cnf)
} else {
res["content"] = rmsbloat(body, cnf)
}
} else if istubayaki(url) {
if !strings.Contains(body, "quoteList") {
res["content"] = rmebloat(body, cnf)
} else {
res["content"] = rmqbloat(body, cnf)
}
} else {
if !strings.Contains(body, "注目のニュース") {
res["content"] = rmebloat(body, cnf)
} else {
res["content"] = rmcbloat(body, cnf)
}
}
res["desc"] = getdesc(res["content"])
}
return res
}

203
rmbloat.go ノーマルファイル
ファイルの表示

@ -0,0 +1,203 @@
package main
import (
"regexp"
"strings"
)
/* カテゴリーだけが残るまで消す */
func rmcbloat(body string, cnf Config) string {
var re *regexp.Regexp
rep := []struct {
pat string
repl string
}{
{`(?s)<!DOCTYPE html>.*?<!--注目のニュース-->`, ""},
{`(?s)<!--/newsCategoryList-->.*?</html>`, ""},
{`(?s)<div class="COMMONDOC_header2017_mainNavHeader.*?</div>`, ""},
{`(?s)<div class="COMMONDOC_header2017_mainNav.*?</div>`, ""},
{`(?s)<div class="COMMONDOC_header2017_toggleNav.*?</div>`, ""},
{`(?s)<div class="COMMONDOC_header2017_localNavArea.*?</div>`, ""},
{`(?s)<div class="COMMONDOC_header2017_globalNav__account.*?</div>`, ""},
{`(?s)<div class="COMMONDOC_header2017_globalNav__logo.*?</div>`, ""},
{`(?s)<div class="COMMONDOC_header2017_globalNav__toggleNav.*?</div>`, ""},
{`(?s)<div class="COMMONDOC_header2017_adBanner.*?</div>`, ""},
{`(?s)<div class="COMMONDOC_header2017_globalNav.*?</div>`, ""},
{`(?s)<div class="COMMONDOC_header2017_globalNavArea.*?</div>`, ""},
{`(?s)<div class="COMMONDOC_header2017_headerArea.*?</div>`, ""},
{`(?s)<div id="page" class="FRAME2016_page">.*?</div>`, ""},
{`(?s)<div id="subCategoryNavi.*?</div>`, ""},
{`(?s)<div role="navigation".*?</div>`, ""},
{`(?s)<div id="div-gpt-ad-.*?</div>`, ""},
{`(?s)<h3.*?</h3>`, ""},
{`(?s)<script.*?</script>`, ""},
{`(?s)<ul class="entryList0.*?</ul>`, ""},
{`(?s)<div class="adMain.*?</div>`, ""},
{`(?s)<div class="gAdComponent.*?</div>`, ""},
{`(?s)<div class="adsense0.*?</div>`, ""},
{`(?s)<div class="adsense.*?</div>`, ""},
{`(?s)<div class="pageList02.*?</div>`, ""},
{`(?s)<span class="reactionCountBalloon.*?</span>`, ""},
{`https://news-image.mixi.net`, cnf.imgproxy + `/news-image.mixi.net`},
{`https://img.mixi.net`, cnf.imgproxy + `/img.mixi.net`},
{`https://news.mixi.jp/`, cnf.domain + `/`},
{``, ""},
{`\[`, ""},
{`\]`, ""},
}
for _, r := range rep {
re = regexp.MustCompile(r.pat)
body = re.ReplaceAllString(body, r.repl)
}
body = strings.TrimSpace("<div class=\"subCategoryNavi\" class=\"LEGACY_UI2016_subCategoryNavi\">\n" + strings.TrimSpace(body)) + "\n </div>\n"
return "<div class=\"newsArticle\">\n<a class=\"totop\" href=\"/\">トップへ</a>\n" + body + "</div>"
}
/* エラーだけが残るまで消す */
func rmebloat(body string, cnf Config) string {
var re *regexp.Regexp
rep := []struct {
pat string
repl string
}{
{`(?s)<!DOCTYPE html>.*?<p class="messageAlert">`, ""},
{`(?s)</p>.*?</html>`, ""},
}
for _, r := range rep {
re = regexp.MustCompile(r.pat)
body = re.ReplaceAllString(body, r.repl)
}
body = strings.TrimSpace("<div class=\"newsArticle\">\n<a class=\"totop\" href=\"/\">トップへ</a>\n" + strings.TrimSpace(body)) + "\n </div>\n"
return body
}
/* つばやきだけが残るまで消す */
func rmqbloat(body string, cnf Config) string {
var re *regexp.Regexp
rep := []struct {
pat string
repl string
}{
{`(?s)<!DOCTYPE html>.*?<div id="bodyMainArea" class="FRAME2016_bodyMainArea" >`, ""},
{`(?s)<div class="adsenseBannerArea">.*?</html>`, ""},
{`(?s)<div class="shareButtonArea">.*?<div class="relationNewsDescription">`, `<div class="relationNewsDescription">`},
{`https://news-image.mixi.net`, cnf.imgproxy + `/news-image.mixi.net`},
{`https://img.mixi.net`, cnf.imgproxy + `/img.mixi.net`},
{`https://news.mixi.jp/`, cnf.domain + `/`},
{`(?s)<div class="sortSwitch01">.*?</div>`, ""},
// {`・ `, ""},
// {`\[`, ""},
// {`\]`, ""},
}
for _, r := range rep {
re = regexp.MustCompile(r.pat)
body = re.ReplaceAllString(body, r.repl)
}
body = strings.TrimSpace("<div class=\"newsArticle\">\n<a class=\"totop\" href=\"/\">トップへ</a>\n" + strings.TrimSpace(body)) + "\n </div>\n"
return body
}
/* 部分圏だけが残るまで消す */
func rmsbloat(body string, cnf Config) string {
var re *regexp.Regexp
rep := []struct {
pat string
repl string
}{
{`(?s)<!DOCTYPE html>.*?<!-- InstanceBeginEditable name="bodyMain" -->`, ""},
{`(?s)<div class="adsenseBannerArea">.*?</html>`, ""},
{`https://news-image.mixi.net`, cnf.imgproxy + `/news-image.mixi.net`},
{`https://img.mixi.net`, cnf.imgproxy + `/img.mixi.net`},
{`https://news.mixi.jp/`, cnf.domain + `/`},
{``, ""},
{`\[`, ""},
{`\]`, ""},
}
for _, r := range rep {
re = regexp.MustCompile(r.pat)
body = re.ReplaceAllString(body, r.repl)
}
body = strings.TrimSpace("<div class=\"newsArticle\">\n<a class=\"totop\" href=\"/\">トップへ</a>\n" + strings.TrimSpace(body)) + "\n </div>\n"
return body
}
/* 出版社だけが残るまで消す */
func rmpbloat(body string, cnf Config) string {
var re *regexp.Regexp
rep := []struct {
pat string
repl string
}{
{`(?s)<!DOCTYPE html>.*?<!-- InstanceBeginEditable name="bodyMain" -->`, ""},
{`(?s)<!-- InstanceEndEditable -->.*?</html>`, ""},
{`(?s)<div class="pageList02.*?</div>`, ""},
{`https://news-image.mixi.net`, cnf.imgproxy + `/news-image.mixi.net`},
{`https://img.mixi.net`, cnf.imgproxy + `/img.mixi.net`},
{`https://news.mixi.jp/`, cnf.domain + `/`},
{``, ""},
{`\[`, ""},
{`\]`, ""},
}
for _, r := range rep {
re = regexp.MustCompile(r.pat)
body = re.ReplaceAllString(body, r.repl)
}
body = strings.TrimSpace("<div class=\"newsArticle\">\n<a class=\"totop\" href=\"/\">トップへ</a>\n" + strings.TrimSpace(body)) + "\n </div>\n"
return body
}
/* 記事だけが残るまで消す */
func rmbloat(id string, body string, cnf Config) string {
var re *regexp.Regexp
rep := []struct {
pat string
repl string
}{
{`(?s)<!DOCTYPE html>.*?<div class="newsArticle">`, ""},
{`(?s)<!--/newsArticle-->.*?</html>`, ""},
{`(?s)<p class="reactions">.*?</p>`, ""},
{`(?s)<ul class="diaryUtility\d*">.*?</ul>`, ""},
{`(?s)<table>.*?</table>`, ""},
{`(?s)<div class="adsense0.*?</div>`, ""},
{`(?s)<div class="adsense.*?</div>`, ""},
{`www\.?youtube\.com`, "youtube.owacon.moe"},
{`(?s)<div class="subInfo">.*?</div>`, ""},
{`(?s)<div class="additional\d*.*?</div>`, ""},
{`(?s)(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+`, "\n"},
{`<!--article_image-->`, ""},
{`<!--/article_image-->`, ""},
{`(?s)<!--.*?-->`, ""},
{`<!--`, ""},
{`(?s)<img src="https://(.*?)"`, `<img src="` + cnf.imgproxy + `/$1"`},
{`https://news-image.mixi.net`, cnf.imgproxy + `/news-image.mixi.net`},
{`https://news.mixi.jp/`, cnf.domain + `/`},
}
for _, r := range rep {
re = regexp.MustCompile(r.pat)
body = re.ReplaceAllString(body, r.repl)
}
body = strings.TrimSpace("<div class=\"newsArticle\">\n<a class=\"totop\" href=\"/\">トップへ</a>\n" + strings.TrimSpace(body))
if id != "" {
body += "\n<p class=\"footer\"><a class=\"tubuyaki-btn\" href=\"/list_quote.pl?news_id=" + id + "&type=voice&sort=feedback_count\">つぶやきを見る</a></p>\n"
}
body += "\n </div>\n"
return body
}

28
spliti.1 ノーマルファイル
ファイルの表示

@ -0,0 +1,28 @@
.TH spliti 1 spliti\-VERSION
.SH ソフト名
mixi向けプライバシーUI。
.SH 概要
.B spliti
[\fI\,オプション\/\fR] [\fI\,ポート番号\/\fR]
.SH 説明
.PP
splitiはmixi向けプライバシーUIです。
.TP
\fB\-v\fR
バージョンを表示
.TP
\fB\-s [ポート番号]\fR
ポート番号でサーバーを開始(デフォルト9930)
.TP
\fB\-h\fR
ヘルプを表示
.SH 会話
.PP
IRC: irc.076.ne.jp/6697 #spliti
.br
メーリングリスト: (開発中)
.SH バグ報告
.PP
バグは下記のURLまでご報告下さい
.br
https://gitler.moe/suwako/spliti/issues

89
srv.go ノーマルファイル
ファイルの表示

@ -0,0 +1,89 @@
package main
import (
"text/template"
"fmt"
"net/http"
"net/url"
"strings"
"log"
"os"
"path/filepath"
)
type Page struct {
Tit, Err, Bdy, Dec, Img, Url, Dom, Ver, Ves string
}
func extractGurl(r *http.Request) (string, error) {
rq := r.URL.RawQuery
q, err := url.QueryUnescape(rq)
if err != nil {
return "URLを受取に失敗", err
}
gurl := strings.Replace(q, "/?url=", "", -1)
return gurl, nil
}
func serv (cnf Config, port int) {
dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
if err != nil {
log.Fatal(err)
}
err = os.Chdir(dir)
if err != nil {
log.Fatal(err)
}
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir(cnf.webpath + "/static"))))
ftmpl := []string{cnf.webpath + "/view/index.html", cnf.webpath + "/view/header.html", cnf.webpath + "/view/footer.html"}
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
// 1.xで、URLは「/?url=」が付いたけど、2.0.0からは不要になった
// だから、下記の部分は古いURLの為だ
urls, ok := r.URL.Query()["url"]
if ok && len(urls[0]) > 0 {
http.Redirect(w, r, "/" + urls[0], http.StatusMovedPermanently)
return
}
data := &Page{Ver: version, Ves: strings.ReplaceAll(version, ".", "")}
uri := r.URL.Path
gurl, err := extractGurl(r)
if err != nil {
data.Tit = "エラー"
data.Err = err.Error()
ftmpl[0] = cnf.webpath + "/view/404.html"
}
if uri == "/" {
ftmpl[0] = cnf.webpath + "/view/index.html"
} else {
furl := uri + "?" + gurl
page := get(furl, cnf)
data.Tit = page["title"]
if page["err"] != "" {
data.Err = page["err"]
ftmpl[0] = cnf.webpath + "/view/404.html"
} else {
data.Bdy = page["content"]
data.Img = "/static/logo.jpg"
if isarticle(furl) {
data.Dec = page["desc"]
data.Img = page["img"]
data.Url = cnf.domain + furl
}
ftmpl[0] = cnf.webpath + "/view/news.html"
}
}
tmpl := template.Must(template.ParseFiles(ftmpl[0], ftmpl[1], ftmpl[2]))
tmpl.Execute(w, data)
data = nil
})
fmt.Println(fmt.Sprint("http://" + cnf.ip + ":", port, " でサーバーを実行中。終了するには、CTRL+Cを押して下さい。"))
http.ListenAndServe(fmt.Sprint(cnf.ip + ":", port), nil)
}

ファイルの表示

@ -1,27 +0,0 @@
server "ドメイン名" {
listen on * port 80
location "/.well-known/acme-challenge/*" {
root "/acme"
request strip 2
}
block return 301 "https://$SERVER_NAME$REQUEST_URI"
}
server "ドメイン名" {
listen on * tls port 443
root "/htdocs/ドメイン名/www"
directory index "index.php"
tls {
certificate "/etc/ssl/ドメイン名.fullchain.pem"
key "/etc/ssl/private/ドメイン名.key"
}
connection { max requests 500, timeout 3600 }
location "/*" {
fastcgi socket "/run/php-fpm.sock"
}
location "/.well-known/acme-challenge/*" {
root "/acme"
request strip 2
}
}

ファイルの表示

@ -1,34 +0,0 @@
server {
server_name ドメイン名;
root /var/www/htdocs/www;
index index.php;
location / {
satisfy any;
allow all;
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
listen 443 ssl http2;
ssl_certificate /etc/letsencrypt/live/ドメイン名/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ドメイン名/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
}
server {
if ($host = ドメイン名) { return 301 https://$host$request_uri; }
listen 80;
server_name ドメイン名;
return 404;
}

バイナリ
static/favicon.ico ノーマルファイル

バイナリファイルは表示されません。

変更後

幅:  |  高さ:  |  サイズ: 15 KiB

ファイルの表示

変更前

幅:  |  高さ:  |  サイズ: 8.3 KiB

変更後

幅:  |  高さ:  |  サイズ: 8.3 KiB

バイナリ
static/logo.jpg ノーマルファイル

バイナリファイルは表示されません。

変更後

幅:  |  高さ:  |  サイズ: 13 KiB

266
static/style.css ノーマルファイル
ファイルの表示

@ -0,0 +1,266 @@
html {
margin: 0;
}
body {
background: #232629;
color: #fcfcfc;
letter-spacing: 0.05em;
}
a {
color: #ea5fea;
text-decoration: none;
}
h1, h2 {
clear: left;
line-height: 1.5;
margin: 15px 0 10px;
padding: 0 0 0 15px;
border-left: 6px solid #f976de;
font-weight: bold;
}
h1 {
font-size: 200%;
}
h2 {
font-size: 166%;
}
code {
background: #e68be6;
padding: 1px;
border-radius: 4px;
border: 1px #fcfcfc solid;
margin: 4px;
color: #232629;
line-height: 2.5;
}
.article > img {
max-width: 100%;
width: auto;
}
.reactionCountBalloon, .totop, p.reactions, a.tubuyaki-btn {
border: 1px solid #f976de;
border-radius: 2px;
background-color: #232629;
}
.reactionCountBalloon {
margin-left: 8px;
font-size: 60%;
padding: 0 12px;
}
.totop, p.reactions {
padding: 4px;
}
p.reactions {
font-size: 80%;
max-width: 50px;
text-align: center;
}
.newsArticle {
width: calc(100% - 20px);
max-width: 1200px;
background: #31363b;
border: 2px solid #4d4d4d;
border-radius: 10px;
margin: 32px auto;
padding: 8px;
}
.newsTable, .NEWS_pickupNewsBox__contentsArea {
width: calc(100% - 20px);
max-width: 1200px;
background: #462146;
border: 2px solid #f976de;
border-radius: 4px;
margin: 20px auto;
}
.NEWS_pickupNewsBox__contentsArea {
background: #58224d;
}
.NEWS_pickupNewsBox__contentsArea, .NEWS_pickupNewsItem {
display: grid;
grid-template-columns: 3fr 1fr;
grid-gap: 8px;
}
.NEWS_pickupNewsTitle, .NEWS_pickupNewsAuthor {
display: inline-grid;
}
.NEWS_pickupNewsTitle__body, .NEWS_pickupNewsAuthor, tr > td.newsTitle > p {
margin: 2px;
}
.NEWS_pickupNewsBox__contentsArea > div {
background: #462146;
}
.odd {
background: #3c213c;
}
.LEGACY_UI2016_subCategoryNavi > p > a, .pageList01 > div > ul > li,
.pageList01 > ul > li, .pageNavigation02 > p.first,
.pageNavigation02 > p.last, ul.sortTab > li,
.pageList02 > ul > li {
background-color: #4d4d4d;
padding: 4px;
border: 1px solid #c625ef;
border-radius: 2px;
text-decoration: none;
}
.pageList01 > div > ul > li:not([class]):hover,
.pageList01 > ul > li:hover,
ul.sortTab > li:hover,
.pageList02 > ul > li[rel="__prev"]:hover,
.pageList02 > ul > li[rel="__next"]:hover,
li.NEWS_pickupNewsItem:hover,
p.NEWS_pickupItems__moreLink:hover,
li.newCategoryList > a:hover,
.photoNewsArea > a:hover,
.NEWS_photoNewsItems__contentsArea:hover,
a.tubuyaki-btn:hover,
p.first:hover, p.last:hover,
tr.odd:hover, tr.even:hover, .totop:hover {
background-color: #ae6bdb;
}
.pageNavigation02 > p, .pageList01 > ul > li, .pageList02 > ul > li {
padding: 8px !important;
}
.pageNavigation02 > p.none, .pageList01 > ul > li.on, ul.sortTab > li.current,
ul.sortTab > li.current > a {
background-color: #232629;
color: #4d4d4d;
border-color: #4d4d4d;
}
.pageList01 > div > ul, .pageList01 > ul, .pageNavigation02 > p.first,
.pageNavigation02 > p.last, ul.sortTab, .pageList02 > ul > li {
padding-left: unset;
}
.pageList01 > div > ul,
.pageList01 > div > ul > li,
.pageList01 > ul > li,
.pageList02 > ul > li,
.entryList01, .entryList01 > li,
.NEWS_pickupNewsList,
.pageNavigation02 > p.first,
.pageNavigation02 > p.last,
ul.sortTab > li,
ul.voiceList01 .attributes li,
ul.listAction,
h2.newsTitle {
display: inline;
}
.pageList02 {
text-align: center;
padding-top: 8px;
}
.relationNewsDescription {
margin-top: 18px;
}
.relationNewsDescription > p.date {
border-left: 3px solid #f976de;
padding: 0 0 0 8px;
}
ul.voiceList01 {
padding-left: 0;
}
.pageNavigation02 {
display: ruby;
}
.newsCategoryList, .timestamp, .iine, .comment, .item {
list-style: none;
}
.itemIn > .clearfix {
display: flex;
}
ul.voiceList01 > li.item {
background-color: #2f2e2f;
border: 1px dashed #4d4d4d;
margin: 8px 0;
padding: 4px;
}
ul.attributes, ul.listAction {
font-size: 80%;
color: #adadad;
}
ul.attributes {
position: absolute;
white-space: nowrap;
}
ul.listAction {
clear: both;
width: 100%;
margin-top: 5px;
margin-left: 4px;
text-align: right;
}
ul.voiceList01 ul.listAction li {
margin-left: 10px;
font-size: 100%;
display: initial;
}
.NEWS_tempPhoto {
text-align: center;
}
.NEWS_tempPhoto__picture {
max-width: 400px;
max-height: 400px;
margin-bottom: 3px;
}
.NEWS_tempPhoto__captionText {
color: #ccc;
text-align: center;
font-size: 86%;
}
.footer {
text-align: center;
margin-top: 32px;
}
li.iine > img, li.comment > img {
margin-right: 8px;
}
a.tubuyaki-btn {
display: inline-table;
padding: 24px;
}
.nextArticle > a.tubuyaki-btn {
text-align: center;
}

4
view/404.html ノーマルファイル
ファイルの表示

@ -0,0 +1,4 @@
{{template "header" .}}
<a href="/">トップへ</a>
{{ .Err }}<br />
{{template "footer" .}}

9
view/footer.html ノーマルファイル
ファイルの表示

@ -0,0 +1,9 @@
{{define "footer"}}
<p class="footer">
<a href="https://technicalsuwako.moe/blog/spliti-{{ .Ves }}/">Spliti {{ .Ver }}</a> |
<a href="https://gitler.moe/suwako/spliti"><img src="/static/git.png" alt="Git"></a> |
<a href="https://076.moe/"></a>
</p>
</body>
</html>
{{end}}

16
view/header.html ノーマルファイル
ファイルの表示

@ -0,0 +1,16 @@
{{define "header"}}<!DOCTYPE html>
<html lang="ja">
<head>
<meta content="text/html; charset=utf-8" http-equiv="content-type" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
{{if ne .Dec "" }}<meta property="og:title" content="spliti 〜 {{ .Tit }}" />
<meta property="og:type" content="article" />
<meta property="og:description" content="{{ .Dec }}" />
<meta property="og:url" content="{{ .Url }}" />{{end}}
<meta name="thumbnail" content="{{ .Img }}" />
<title>spliti 〜 {{ .Tit }}</title>
<link rel="icon" type="image/x-icon" href="/static/favicon.ico" />
<link rel="stylesheet" type="text/css" href="/static/style.css" />
</head>
<body>
{{end}}

21
view/index.html ノーマルファイル
ファイルの表示

@ -0,0 +1,21 @@
{{template "header" .}}
<div class="newsArticle">
<div class="newsCategoryList">
<div class="heading08">
<h1>ニュースカテゴリ一覧</h1>
</div>
<ul class="newsCategoryList">
<li class="newCategoryList"><a href="/list_news_category.pl?id=7">エンタメ</a></li>
<li class="newCategoryList"><a href="/list_news_category.pl?id=3">トレンド</a></li>
<li class="newCategoryList"><a href="/list_news_category.pl?id=1">社会</a></li>
<li class="newCategoryList"><a href="/list_news_category.pl?id=4">地域</a></li>
<li class="newCategoryList"><a href="/list_news_category.pl?id=9">ゲーム・アニメ</a></li>
<li class="newCategoryList"><a href="/list_news_category.pl?id=8">IT・インターネット</a></li>
<li class="newCategoryList"><a href="/list_news_category.pl?id=6">スポーツ</a></li>
<li class="newCategoryList"><a href="/list_news_category.pl?id=5">海外</a></li>
<li class="newCategoryList"><a href="/list_news_category.pl?id=10">コラム</a></li>
<li class="newCategoryList"><a href="/list_news_category.pl?id=2">ライフスタイル</a></li>
</ul>
</div>
</div>
{{template "footer" .}}

3
view/news.html ノーマルファイル
ファイルの表示

@ -0,0 +1,3 @@
{{template "header" .}}
{{ .Bdy }}
{{template "footer" .}}

ファイルの表示

@ -1,107 +0,0 @@
<?php
include("../config.php");
/* ページのタイトル */
function gettitle (string $str): string {
preg_match("/<title>(.*)<\/title>/", $str, $matches);
return $matches[1];
}
function getimg (string $str): string {
preg_match('/<img class="NEWS_tempPhoto__picture" src="(.*)" alt="">/', $str, $matches);
return $matches[1];
}
function getdesc (string $str): string {
$res = preg_replace('/<div class="newsArticle">(.*?)<\/div>/s', "", $str);
return strip_tags($res);
}
/* 記事かの確認 */
function isarticle (string $url): bool {
$chk = explode("=", $url);
if (isset($chk[0]) && $chk[0] == "view_news.pl?id" && isset($chk[1]) && isset($chk[2])) {
$chk2 = explode("&amp;", $chk[1]);
if (isset($chk2[1]) && $chk2[1] == "media_id") return true;
}
return false;
}
/* 記事だけが残るまで消す */
function rmbloat (string $body): string {
$res = preg_replace('/<!DOCTYPE html>(.*?)<div class="newsArticle">/s', "", $body);
$res = preg_replace('/<!--\/newsArticle-->(.*?)<\/html>/s', "", $res);
$res = preg_replace('/<p class="reactions">(.*?)<\/p>/s', "", $res);
$res = preg_replace('/<ul class="diaryUtility\d*">(.*?)<\/ul>/s', "", $res);
$res = preg_replace('/<table>(.*?)<\/table>/s', "", $res);
$res = preg_replace('/<div class="adsense0(.*?)<\/div>/s', "", $res);
$res = preg_replace('/<div class="adsense(.*?)<\/div>/s', "", $res);
$res = preg_replace('/<div class="subInfo">(.*?)<\/div>/s', "", $res);
$res = preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $res);
$res = str_replace("<!--article_image-->", "", $res);
$res = str_replace("<!--/article_image-->", "", $res);
$res = preg_replace("/<!--(.*)-->/", "", $res);
$res = str_replace("<!--", "", $res);
return trim("<div class=\"newsArticle\">\n".trim($res))."\n </div>\n";
}
/* 記事の受取 */
function get (string $url = ""): array {
$res = [];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://news.mixi.jp/".$url);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"HTTP/1.0",
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language: en-US,en;q=0.5",
"Connection: keep-alive",
"User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0"
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$body = mb_convert_encoding(curl_exec($ch), "UTF-8", "EUC-JP");
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($body && $httpCode == 200) {
$res["title"] = gettitle($body);
$res["content"] = rmbloat($body);
$res["img"] = getimg($body);
$res["desc"] = getdesc($res["content"]);
}
return $res;
}
// URLを受け取って、mixiにわかれるURLに変更
$gurl = str_replace("/?url=", "", htmlspecialchars($_SERVER["REQUEST_URI"]));
// デフォルト=エラー
$out = ["title" => "見つけられない", "content" => '<div class="newsArticle"><div class="articleHeading02"><div class="headingArea"><h1>見つけられなかった</h1></div></div><div class="contents clearfix"><div class="article decoratable"><p>ごめんね!</p></div></div>'];
// $gurlは「/」だったら、トップページを表示する。記事だったら、記事を表示する。
if ($gurl == "/") $out = ["title" => "トップページ", "content" => '<div class="newsArticle"><div class="articleHeading02"><div class="headingArea"><h1>使い方</h1></div></div><div class="contents clearfix"><div class="article decoratable"><p><code>https://news.mixi.jp/view_news.pl?id=********&media_id=***</code>→<code>'.DOMAIN.'/?url=view_news.pl?id=********&media_id=***</code><br />例えば:<code>https://news.mixi.jp/view_news.pl?id=7327623&media_id=4</code>→<code>'.DOMAIN.'/?url=view_news.pl?id=7327047&media_id=262</code></p></div></div>'];
else if (isarticle($gurl)) $out = get($gurl);
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta content="text/html; charset=euc-jp" http-equiv="content-type" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<?php if (isset($out["desc"])) { ?>
<meta property="og:title" content="spliti 〜 <?= $out["title"] ?>" />
<meta property="og:type" content="article" />
<meta property="og:description" content="<?= $out["desc"] ?>" />
<meta property="og:url" content="<?= $gurl ?>" />
<?php } ?>
<?php if (isset($out["img"])) { ?><meta name="thumbnail" content="<?= $out["img"] ?>" /><?php } ?>
<title>spliti <?= $out["title"] ?></title>
<link rel="stylesheet" type="text/css" href="/style.css" />
</head>
<body>
<?= $out["content"] ?>
<p class="footer">
<a href="https://gitler.moe/suwako/spliti"><img src="/git.png" alt="Git"></a> |
<a href="https://076.moe"></a>
</p>
</body>
</html>

ファイルの表示

@ -1,64 +0,0 @@
html {
margin: 0;
}
body {
background: #232629;
color: #fcfcfc;
letter-spacing: 0.05em;
}
a {
color: #ea5fea;
}
h2 {
clear: left;
line-height: 1.5;
margin: 15px 0 10px;
padding: 0 0 0 15px;
border-left: 6px solid #f976de;
font-weight: bold;
font-size: 166%;
}
code {
background: #e68be6;
padding: 1px;
border-radius: 4px;
border: 1px #fcfcfc solid;
margin: 4px;
color: #232629;
line-height: 2.5;
}
.newsArticle {
width: calc(100% - 20px);
max-width: 1200px;
background: #31363b;
border: 2px solid #4d4d4d;
border-radius: 10px;
margin: auto;
padding: 8px;
}
.NEWS_tempPhoto {
text-align: center;
}
.NEWS_tempPhoto__picture {
max-width: 400px;
max-height: 400px;
margin-bottom: 3px;
}
.NEWS_tempPhoto__captionText {
color: #ccc;
text-align: center;
font-size: 86%;
}
.footer {
text-align: center;
margin-top: 32px;
}