1
0
mirror of https://github.com/fumiama/CMoe-Counter.git synced 2024-11-23 22:00:56 +01:00
This commit is contained in:
源文雨 2021-06-07 21:18:19 +08:00
parent af031718a4
commit 2c537be0ad
58 changed files with 523 additions and 0 deletions

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
.vscode
# production
build
# misc
.DS_Store

12
CMakeLists.txt Normal file
View File

@ -0,0 +1,12 @@
cmake_minimum_required(VERSION 2.6)
project(CMoe-Counter C)
SET(CMAKE_BUILD_TYPE "Release")
include_directories("/usr/local/include")
link_directories("/usr/local/lib")
add_executable(cmoe cmoe.c)
target_link_libraries(cmoe spb)
INSTALL(TARGETS cmoe RUNTIME DESTINATION bin)

60
README.md Normal file
View File

@ -0,0 +1,60 @@
# Moe-counter
多种风格可选的萌萌计数器
![Moe-counter](https://count.getloli.com/get/@Moe-counter.github)
<details>
<summary>More theme</summary>
##### moebooru(mb)
![moebooru](https://count.getloli.com/get/@demo?theme=moebooru)
##### rule34(r34)
![Rule34](https://count.getloli.com/get/@demo?theme=rule34)
##### gelbooru(gb)
![Gelbooru](https://count.getloli.com/get/@demo?theme=gelbooru)</details>
## Demo
[https://count.getloli.com](https://count.getloli.com)
## Usage
### Install [simple-http-server](https://github.com/fumiama/simple-http-server)
Follow the instructions in [this repo](https://github.com/fumiama/simple-http-server) to install it.
### Install CMoe
```bash
git clone https://github.com/fumiama/CMoe-Counter.git
cd CMoe-Counter
mkdir build
cd build
cmake ..
make
make install
```
### Copy files
1. Copy `favicon.ico`, `index.html`, `style.css` and the compiled binary `cmoe` into the same folder.
2. Run `simple-http-server` by the command
```bash
simple-http-server -d port folder
```
### Enjoy it!
## API
The API of CMoe is simpler than [Moe-counter](https://github.com/journey-ad/Moe-counter)
### Register
`token` is defined in `cmoe.h`
```
http://yourdomain/cmoe?name=yourname&reg=token
```
### Refer
```
http://yourdomain/cmoe?name=yourname(&theme=mb/mbh/gb/gbh/r34)
```
That's all.
## Credits
* [Moe-counter](https://github.com/journey-ad/Moe-counter)
* [moebooru](https://github.com/moebooru/moebooru)
* rule34.xxx NSFW
* gelbooru.com NSFW
* [Icons8](https://icons8.com/icons/set/star)

BIN
assets/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

117
assets/index.html Normal file
View File

@ -0,0 +1,117 @@
<html>
<head>
<title>Moe Counter!</title>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<link rel="icon" type="image/png" href="favicon.png"/>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/kognise/water.css@latest/dist/light.min.css"/>
<link rel="stylesheet" href="style.css"/>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async="async" src="https://www.googletagmanager.com/gtag/js?id=G-2RLWN5JXRL"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'G-2RLWN5JXRL');
function _evt_push(type, category, label) {
gtag('event', type, {
'event_category': category,
'event_label': label
});
}
</script>
</head>
<body>
<h3>How to use:</h3>
<h5>SVG address</h5>
<code>https://count.getloli.com/get/@:name</code>
<h5>Img tag</h5>
<code>&lt;img src="https://count.getloli.com/get/@:name" alt=":name" /></code>
<h5>Markdown</h5>
<code>![:name](https://count.getloli.com/get/@:name)</code>
<h3>
eg:<img src="https://count.getloli.com/get/@index" alt="Moe Count!"/>
</h3>
<i>
Data can access by anyone, please<span style="color: #ff4500;">DO NOT</span>
enter personal information
</i>
<details>
<summary style="display: inline-block;" onclick="_evt_push(&quot;click&quot;, &quot;normal&quot;, &quot;more_theme&quot;)">
<h3 style="display: inline-block; cursor: pointer;">More theme</h3>
</summary>
<p style="margin: 0;">
Just use the query parameters <code>theme</code>
, like this: <code>https://count.getloli.com/get/@:name?theme=moebooru</code>
</p>
<h5>moebooru</h5>
<img src="https://count.getloli.com/get/@demo?theme=moebooru" alt="Moebooru"/>
<h5>moebooru-h</h5>
<img src="https://count.getloli.com/get/@demo?theme=moebooru-h" alt="Moebooru-Hentai"/>
<h5>rule34</h5>
<img src="https://count.getloli.com/get/@demo?theme=rule34" alt="Rule34"/>
<h5>gelbooru</h5>
<img src="https://count.getloli.com/get/@demo?theme=gelbooru" alt="Gelbooru"/>
<h5>gelbooru-h</h5>
<img src="https://count.getloli.com/get/@demo?theme=gelbooru-h" alt="Gelbooru-Hentai"/>
</details>
<h3>Credits</h3>
<ul>
<li>
<a href="https://repl.it/" target="_blank" rel="nofollow">repl.it</a>
</li>
<li>
<a href="https://github.com/moebooru/moebooru" target="_blank" rel="nofollow">moebooru</a>
</li>
<li>
<a href="javascript:alert(&quot;!!! NSFW LINK !!!\nPlease enter the url manually&quot;)">rule34.xxx</a>
NSFW
</li>
<li>
<a href="javascript:alert(&quot;!!! NSFW LINK !!!\nPlease enter the url manually&quot;)">gelbooru.com</a>
NSFW
</li>
<li>
<a href="https://icons8.com/icons/set/star" target="_blank" rel="nofollow">Icons8</a>
</li>
</ul>
<h3>Tool</h3>
<div class="tool">
<code>https://count.getloli.com/get/@</code>
<input id="name" type="text" placeholder=":name" style="display: inline-block; width: 80px; height: 1.4em; line-height: 1.4em; margin: 0 4px; vertical-align: middle;"/>
<code>?theme=</code>
<select id="theme" style="display: inline-block; height: 1.6em; line-height: 1.6em; font-size: 14px; margin: 0 4px; padding: 0 4px; vertical-align: middle;">
<option value="moebooru">moebooru</option>
<option value="moebooru-h">moebooru-h</option>
<option value="rule34">rule34</option>
<option value="gelbooru">gelbooru</option>
<option value="gelbooru-h">gelbooru-h</option>
</select>
<button id="get" style="margin: 10px 0;" onclick="_evt_push(&quot;click&quot;, &quot;normal&quot;, &quot;get_counter&quot;)">Get</button>
<img id="result" style="display: block;"/>
<script>
var btn = document.getElementById('get')
, img = document.getElementById('result')
btn.addEventListener('click', function() {
var name = document.getElementById('name')
, themeEl = document.getElementById('theme')
var text = name.value ? name.value.trim() : ''
var theme = themeEl.value || 'moebooru'
if (!text) {
alert('Please input counter name.')
return
}
img.src = 'https://count.getloli.com/get/@' + text + '?theme=' + theme
})
</script>
</div>
<p class="copy">
<a href="https://github.com/journey-ad/Moe-counter" target="_blank" onclick="_evt_push(&quot;click&quot;, &quot;normal&quot;, &quot;go_github&quot;)">source code</a>
</p>
</body>
</html>

5
assets/style.css Normal file
View File

@ -0,0 +1,5 @@
@media screen and (max-width: 900px) {
iframe {
display: none;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
assets/theme/gelbooru/0.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
assets/theme/gelbooru/1.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
assets/theme/gelbooru/2.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
assets/theme/gelbooru/3.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
assets/theme/gelbooru/4.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
assets/theme/gelbooru/5.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
assets/theme/gelbooru/6.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
assets/theme/gelbooru/7.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
assets/theme/gelbooru/8.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
assets/theme/gelbooru/9.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 680 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 769 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 855 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 775 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 819 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 795 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1012 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 913 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 826 B

BIN
assets/theme/moebooru/0.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
assets/theme/moebooru/1.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 922 B

BIN
assets/theme/moebooru/2.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
assets/theme/moebooru/3.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 974 B

BIN
assets/theme/moebooru/4.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
assets/theme/moebooru/5.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
assets/theme/moebooru/6.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
assets/theme/moebooru/7.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
assets/theme/moebooru/8.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
assets/theme/moebooru/9.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
assets/theme/rule34/0.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
assets/theme/rule34/1.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

BIN
assets/theme/rule34/2.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

BIN
assets/theme/rule34/3.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
assets/theme/rule34/4.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

BIN
assets/theme/rule34/5.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

BIN
assets/theme/rule34/6.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

BIN
assets/theme/rule34/7.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

BIN
assets/theme/rule34/8.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
assets/theme/rule34/9.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

210
cmoe.c Normal file
View File

@ -0,0 +1,210 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <simple_protobuf.h>
#include "cmoe.h"
static uint32_t* items_len;
static COUNTER counter;
#define ADD_HERDER(h)\
strcpy(buf + offset, (h));\
offset += sizeof((h)) - 1;
#define ADD_HERDER_PARAM(h, p)\
sprintf(buf + offset, (h), (p));\
offset += strlen(buf + offset);
#define EXTNM_IS_NOT(name) (strcmp(filepath+extpos, name))
static void headers(u_int32_t content_len, const char* content_type, int no_cache) {
char buf[1024];
u_int32_t offset = 0;
ADD_HERDER(HTTP200 SERVER_STRING);
if(no_cache) ADD_HERDER(CACHE_CTRL);
ADD_HERDER_PARAM(CONTENT_TYPE, content_type);
ADD_HERDER_PARAM(CONTENT_LEN "\r\n", content_len);
fwrite(buf, offset, 1, stdout);
}
static void http_error(char* type, char* msg) {
fprintf(stdout, type, msg);
exit(EXIT_FAILURE);
}
static char* get_arg(char* query) {
u_int32_t len = 0;
while(query[len] && query[len] != '&') len++;
if(len > 0) {
char* name = malloc(len+1);
memcpy(name, query, len);
name[len] = 0;
return name;
} else return NULL;
}
static int del_user(FILE* fp, SIMPLE_PB* spb) {
COUNTER *d = (COUNTER *)spb->target;
uint32_t next = ftell(fp);
uint32_t this = next - spb->real_len;
fseek(fp, 0, SEEK_END);
uint32_t end = ftell(fp);
if(next == end) {
return ftruncate(fileno(fp), end - spb->real_len);
} else {
uint32_t cap = end - next;
char *data = malloc(cap);
if(data) {
fseek(fp, next, SEEK_SET);
if(fread(data, cap, 1, fp) == 1) {
if(!ftruncate(fileno(fp), end - spb->real_len)){
fseek(fp, this, SEEK_SET);
if(fwrite(data, cap, 1, fp) == 1) {
free(data);
return 0;
}
}
}
free(data);
}
return 2;
}
}
static int add_user(char* name, uint32_t count, FILE* fp) {
counter.count = count;
strncpy(counter.name, name, COUNTER_NAME_LEN-1);
fseek(fp, 0, SEEK_END);
return !set_pb(fp, items_len, sizeof(COUNTER), &counter);
}
static uint32_t get_content_len(int isbig, uint16_t* len_type, char* cntstr) {
uint32_t len = sizeof(svg_small) - 1
+ (sizeof(img_slot_front) + sizeof(img_slot_rear) - 2) * 10
+ 16 + isbig
+ sizeof(svg_tail) - 1;
for(int i = 0; i < 10; i++) {
len += len_type[cntstr[i] - '0'];
}
return len;
}
#define has_next(fp, ch) ((ch=getc(fp)),(feof(fp)?0:(ungetc(ch,fp),1)))
#define set_type(name, t, l) if(!strcmp(theme, name)) {\
theme_type = t;\
len_type = l;\
}
static void return_count(char* name, char* theme) {
FILE* fp = fopen(DATFILE, "rb+");
if(!fp) fp = fopen(DATFILE, "wb+");
if(fp) {
int ch, exist = 0;
while(has_next(fp, ch)) {
SIMPLE_PB *spb = get_pb(fp);
COUNTER *d = (COUNTER *)spb->target;
if (!strcmp(name, d->name)) {
if(del_user(fp, spb)) http_error(HTTP500, "Unable to Delete Old Data.");
else {
if (add_user(d->name, d->count + 1, fp)) http_error(HTTP500, "Add User Error.");
else {
fflush(fp);
char cntstr[11];
sprintf(cntstr, "%010u", d->count);
int isbig = 0;
char** theme_type = mb;
uint16_t* len_type = mbl;
if(theme) {
set_type("mbh", mbh, mbhl) else
set_type("r34", r34, r34l) else
set_type("gb", gb, gbl) else
set_type("gbh", gbh, gbhl)
isbig = (theme_type == gb || theme_type == gbh);
}
int w, h;
char *head;
if(isbig) {
w = W_BIG;
h = H_BIG;
head = svg_big;
}
else {
w = W_SMALL;
h = H_SMALL;
head = svg_small;
}
headers(get_content_len(isbig, len_type, cntstr), "image/svg+xml", 1);
fwrite(head, sizeof(svg_small)-1, 1, stdout);
for(int i = 0; i < 10; i++) {
printf(img_slot_front, w * i, w, h);
int n = cntstr[i] - '0';
fwrite(theme_type[n], len_type[n], 1, stdout);
printf(img_slot_rear);
}
fwrite(svg_tail, sizeof(svg_tail)-1, 1, stdout);
}
free(spb);
return;
}
}
else free(spb);
}
fclose(fp);
http_error(HTTP404, "No Such User.");
} else http_error(HTTP500, "Open File Error.");
}
static int name_exist(char* name) {
FILE* fp = fopen(DATFILE, "rb+");
if(!fp) fp = fopen(DATFILE, "wb+");
if(fp) {
int ch, exist = 0;
while(has_next(fp, ch)) {
SIMPLE_PB *spb = get_pb(fp);
COUNTER *d = (COUNTER *)spb->target;
if (!strcmp(name, d->name)) {
return 1;
}
else free(spb);
}
fclose(fp);
return 0;
} else http_error(HTTP500, "Open File Error.");
}
#define QS (argv[2])
//Usage: cmoe method query_string
int main(int argc, char **argv) {
if(argc == 3) {
u_int32_t data_len = 0;
char* name = strstr(QS, "name=");
items_len = align_struct(sizeof(COUNTER), 2, &counter.name, &counter.count);
if(!items_len) http_error(HTTP500, "Align Struct Error.");
else if(name) {
name = get_arg(name + 5);
if(name) {
char* theme = strstr(QS, "theme=");
if(theme) {
theme = get_arg(theme + 6);
}
char* reg = strstr(QS, "reg=");
if(reg) {
reg = get_arg(reg + 4);
if(reg) {
if(strcmp(reg, "fumiama")) http_error(HTTP400, "Token Error.");
else if(!name_exist(name)) {
FILE* fp = fopen(DATFILE, "ab+");
if(fp) {
add_user(name, 0, fp);
char* msg = "<P>Success.\r\n";
headers(strlen(msg), "text/html", 1);
fwrite(msg, strlen(msg), 1, stdout);
fclose(fp);
} else http_error(HTTP500, "Open File Error.");
} else http_error(HTTP400, "Name Exist.");
} else http_error(HTTP400, "Null Register Token.");
} else return_count(name, theme);
} else http_error(HTTP400, "Null Name Argument.");
} else http_error(HTTP400, "Name Argument Notfound.");
} else http_error(HTTP500, "Argument Count Error.");
return 0;
}

112
cmoe.h Normal file

File diff suppressed because one or more lines are too long