Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified .yarn/install-state.gz
Binary file not shown.
6 changes: 1 addition & 5 deletions get/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,4 @@ for await (const shift of getShiftCodes()) {
console.log(shift.code);
}

```

## Source Attribution

- https://shift.orcicorn.com/shift/
```
2 changes: 2 additions & 0 deletions get/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@
"branch": "master"
},
"devDependencies": {
"@types/cheerio": "^0.22.35",
"@types/node": "^22.18.6",
"@types/node-fetch": "2.6.4",
"typescript": "^5.9.2"
},
"dependencies": {
"cheerio": "^1.1.2",
"node-fetch": "^2.7.0",
"stream-json": "^1.9.1"
},
Expand Down
4 changes: 2 additions & 2 deletions get/src/codes.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { getOrcicornShiftCodes } from './source/orcicorn';
import { getCodeVaultShiftCodes } from './source/codevault';
import { getMentalMarsShiftCodes } from './source/mentalmars';

export async function * getShiftCodes() {
yield * getCodeVaultShiftCodes();
yield * getOrcicornShiftCodes();
yield * getMentalMarsShiftCodes();
}
31 changes: 31 additions & 0 deletions get/src/source/mentalmars/bl1.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import fetch from 'node-fetch';
import * as cheerio from 'cheerio';

import { ShiftCode } from '../../types';
import { parseTableRow } from './shared';

const SHIFT_CODES_URL = 'https://mentalmars.com/game-news/borderlands-golden-keys/';

export async function * getMentalMarsBL1ShiftCodes(): AsyncGenerator<ShiftCode> {
const response = await fetch(SHIFT_CODES_URL);

const text = await response.text();
const $ = cheerio.load(text);

yield * getHeadingShiftCodes($, 'h-2026-shift-codes');
yield * getHeadingShiftCodes($, 'h-2025-shift-codes');
yield * getHeadingShiftCodes($, 'h-2024-shift-codes');
yield * getHeadingShiftCodes($, 'h-legacy-codes-that-work-in-2025');
}

export async function * getHeadingShiftCodes($: cheerio.Root, heading: string, platform: string = 'Universal'): AsyncGenerator<ShiftCode> {
const figure = $(`#${heading} ~ figure`).first();

const parseRow = parseTableRow($, 'Borderlands', platform);

const rows = figure.find('tbody tr');
for (const row of rows) {
const code = parseRow(row);
if (code) yield code;
}
}
34 changes: 34 additions & 0 deletions get/src/source/mentalmars/bl2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import fetch from 'node-fetch';
import * as cheerio from 'cheerio';

import { ShiftCode } from '../../types';
import { parseTableRow } from './shared';

const SHIFT_CODES_URL = 'https://mentalmars.com/game-news/borderlands-2-golden-keys/';

export async function * getMentalMarsBL2ShiftCodes(): AsyncGenerator<ShiftCode> {
const response = await fetch(SHIFT_CODES_URL);

const text = await response.text();
const $ = cheerio.load(text);

yield * getHeadingShiftCodes($, 'h-2026-shift-codes');
yield * getHeadingShiftCodes($, 'h-2025-shift-codes');
yield * getHeadingShiftCodes($, 'h-2024-shift-codes');
yield * getHeadingShiftCodes($, 'h-pc-codes-with-no-expiration-date', 'Steam');
yield * getHeadingShiftCodes($, 'h-xbox-codes-with-no-expiration-date', 'Xbox');
yield * getHeadingShiftCodes($, 'h-playstation-codes-with-no-expiration-date', 'Playstation');
yield * getHeadingShiftCodes($, 'h-special-event-codes');
}

export async function * getHeadingShiftCodes($: cheerio.Root, heading: string, platform: string = 'Universal'): AsyncGenerator<ShiftCode> {
const figure = $(`#${heading} ~ figure`).first();

const parseRow = parseTableRow($, 'Borderlands 2', platform);

const rows = figure.find('tbody tr');
for (const row of rows) {
const code = parseRow(row);
if (code) yield code;
}
}
33 changes: 33 additions & 0 deletions get/src/source/mentalmars/bl3.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import fetch from 'node-fetch';
import * as cheerio from 'cheerio';

import { ShiftCode } from '../../types';
import { parseTableRow } from './shared';

const SHIFT_CODES_URL = 'https://mentalmars.com/game-news/borderlands-3-golden-keys/';

export async function * getMentalMarsBL3ShiftCodes(): AsyncGenerator<ShiftCode> {
const response = await fetch(SHIFT_CODES_URL);

const text = await response.text();
const $ = cheerio.load(text);

yield * getHeadingShiftCodes($, 'h-2026-shift-codes');
yield * getHeadingShiftCodes($, 'h-2025-shift-codes');
yield * getHeadingShiftCodes($, 'h-2024-shift-codes');
yield * getHeadingShiftCodes($, 'h-borderlands-3-cosmetic-shift-code-rewards');
yield * getHeadingShiftCodes($, 'h-borderlands-3-diamond-key-shift-codes');
yield * getHeadingShiftCodes($, 'h-borderlands-3-permanent-shift-keys');
}

export async function * getHeadingShiftCodes($: cheerio.Root, heading: string, platform: string = 'Universal'): AsyncGenerator<ShiftCode> {
const figure = $(`#${heading} ~ figure`).first();

const parseRow = parseTableRow($, 'Borderlands 3', platform);

const rows = figure.find('tbody tr');
for (const row of rows) {
const code = parseRow(row);
if (code) yield code;
}
}
24 changes: 24 additions & 0 deletions get/src/source/mentalmars/bl4.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import fetch from 'node-fetch';
import * as cheerio from 'cheerio';

import { ShiftCode } from '../../types';
import { parseTableRow } from './shared';

const SHIFT_CODES_URL = 'https://mentalmars.com/game-news/borderlands-4-shift-codes/';

export async function * getMentalMarsBL4ShiftCodes(): AsyncGenerator<ShiftCode> {
const response = await fetch(SHIFT_CODES_URL);

const text = await response.text();
const $ = cheerio.load(text);

const figure = $('#h-every-borderlands-4-shift-code-for-golden-keys ~ figure').first();

const parseRow = parseTableRow($, 'Borderlands 4', 'Universal');

const rows = figure.find('tbody tr');
for (const row of rows) {
const code = parseRow(row);
if (code) yield code;
}
}
38 changes: 38 additions & 0 deletions get/src/source/mentalmars/godfall.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import fetch from 'node-fetch';
import * as cheerio from 'cheerio';

import { ShiftCode } from '../../types';
import { SHIFT_CODE_REGEX } from '../../const';
import { parseDate } from '../../utils/parseDate';

const SHIFT_CODES_URL = 'https://mentalmars.com/game-news/godfall-shift-codes/';

export async function * getMentalMarsGodfallShiftCodes(): AsyncGenerator<ShiftCode> {
const response = await fetch(SHIFT_CODES_URL);

const text = await response.text();
const $ = cheerio.load(text);

const figure = $('#h-new-godfall-shift-codes ~ figure').first();

const rows = figure.find('tbody tr');
for (const row of rows) {
const cells = $(row).find('td');

const reward = $(cells.get(0)).text();
const created = $(cells.get(1)).text();
const code = $(cells.get(2)).find('code').text().match(SHIFT_CODE_REGEX)?.[0];

if (!code) continue;

const shiftCode: ShiftCode = {
code,
game: 'Godfall',
platform: 'Universal',
reward,
created: parseDate(created),
};

yield shiftCode;
}
}
20 changes: 20 additions & 0 deletions get/src/source/mentalmars/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { ShiftCode } from "../../types";
import { getMentalMarsBL1ShiftCodes } from "./bl1";
import { getMentalMarsBL2ShiftCodes } from "./bl2";
import { getMentalMarsBL3ShiftCodes } from "./bl3";
import { getMentalMarsBL4ShiftCodes } from "./bl4";
import { getMentalMarsTTWShiftCodes } from "./ttw";
import { getMentalMarsTPSShiftCodes } from "./tps";
import { getMentalMarsNTBShiftCodes } from "./ntb";
import { getMentalMarsGodfallShiftCodes } from "./godfall";

export async function * getMentalMarsShiftCodes(): AsyncGenerator<ShiftCode> {
yield* getMentalMarsBL4ShiftCodes();
yield* getMentalMarsBL3ShiftCodes();
yield* getMentalMarsBL2ShiftCodes();
yield* getMentalMarsBL1ShiftCodes();
yield* getMentalMarsTTWShiftCodes();
yield* getMentalMarsTPSShiftCodes();
yield* getMentalMarsNTBShiftCodes();
yield* getMentalMarsGodfallShiftCodes();
}
26 changes: 26 additions & 0 deletions get/src/source/mentalmars/ntb.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import fetch from 'node-fetch';
import * as cheerio from 'cheerio';

import { ShiftCode } from '../../types';
import { SHIFT_CODE_REGEX } from '../../const';
import { parseDate } from '../../utils/parseDate';
import { parseTableRow } from './shared';

const SHIFT_CODES_URL = 'https://mentalmars.com/game-news/new-tales-from-the-borderlands-shift-codes/';

export async function * getMentalMarsNTBShiftCodes(): AsyncGenerator<ShiftCode> {
const response = await fetch(SHIFT_CODES_URL);

const text = await response.text();
const $ = cheerio.load(text);

const figure = $('figure').first();

const parseRow = parseTableRow($, 'New Tales of the Borderlands', 'Universal');

const rows = figure.find('tbody tr');
for (const row of rows) {
const code = parseRow(row);
if (code) yield code;
}
}
34 changes: 34 additions & 0 deletions get/src/source/mentalmars/shared.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import * as cheerio from 'cheerio';

import { SHIFT_CODE_REGEX } from "../../const";
import { ShiftCode } from "../../types";
import { parseDate } from "../../utils/parseDate";

export const parseTableRow = ($: cheerio.Root, game: string, platform: string) => (row: cheerio.Element): ShiftCode | null => {
const cells = $(row).find('td');

let reward: string = 'Unknown';
let expired: string | undefined;
let code: string | undefined;

if (cells.length === 3) {
reward = $(cells.get(0)).text();
expired = $(cells.get(1)).text().replace('Expires:', '').trim();
code = $(cells.get(2)).find('code').text().match(SHIFT_CODE_REGEX)?.[0];
} else if (cells.length === 2) {
reward = $(cells.get(0)).text();
code = $(cells.get(1)).find('code').text().match(SHIFT_CODE_REGEX)?.[0];
}

if (!code) return null;

const shiftCode: ShiftCode = {
code,
game,
platform,
reward,
expired: expired ? parseDate(expired) : undefined
};

return shiftCode;
}
34 changes: 34 additions & 0 deletions get/src/source/mentalmars/tps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import fetch from 'node-fetch';
import * as cheerio from 'cheerio';

import { ShiftCode } from '../../types';
import { parseTableRow } from './shared';

const SHIFT_CODES_URL = 'https://mentalmars.com/game-news/bltps-golden-keys/';

export async function * getMentalMarsTPSShiftCodes(): AsyncGenerator<ShiftCode> {
const response = await fetch(SHIFT_CODES_URL);

const text = await response.text();
const $ = cheerio.load(text);

yield * getHeadingShiftCodes($, 'h-2026-shift-codes');
yield * getHeadingShiftCodes($, 'h-2025-shift-codes');
yield * getHeadingShiftCodes($, 'h-2024-shift-codes');
yield * getHeadingShiftCodes($, 'h-permanent-bltps-shift-codes-for-golden-keys');
yield * getHeadingShiftCodes($, 'h-bltps-pc-shift-codes', 'Steam');
yield * getHeadingShiftCodes($, 'h-bltps-playstation-shift-codes', 'Playstation');
yield * getHeadingShiftCodes($, 'h-bltps-xbox-shift-codes', 'Xbox');
}

export async function * getHeadingShiftCodes($: cheerio.Root, heading: string, platform: string = 'Universal'): AsyncGenerator<ShiftCode> {
const figure = $(`#${heading} ~ figure`).first();

const parseRow = parseTableRow($, 'Borderlands: The Pre-Sequel', platform);

const rows = figure.find('tbody tr');
for (const row of rows) {
const code = parseRow(row);
if (code) yield code;
}
}
31 changes: 31 additions & 0 deletions get/src/source/mentalmars/ttw.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import fetch from 'node-fetch';
import * as cheerio from 'cheerio';

import { ShiftCode } from '../../types';
import { parseTableRow } from './shared';

const SHIFT_CODES_URL = 'https://mentalmars.com/game-news/tiny-tinas-wonderlands-shift-codes/';

export async function * getMentalMarsTTWShiftCodes(): AsyncGenerator<ShiftCode> {
const response = await fetch(SHIFT_CODES_URL);

const text = await response.text();
const $ = cheerio.load(text);

yield * getHeadingShiftCodes($, 'h-2026-shift-codes');
yield * getHeadingShiftCodes($, 'h-2025-shift-codes');
yield * getHeadingShiftCodes($, 'h-2024-shift-codes');
yield * getHeadingShiftCodes($, 'h-permanent-ttwl-shift-codes');
}

export async function * getHeadingShiftCodes($: cheerio.Root, heading: string, platform: string = 'Universal'): AsyncGenerator<ShiftCode> {
const figure = $(`#${heading} ~ figure`).first();

const parseRow = parseTableRow($, 'Tiny Tina\'s Wonderlands', platform);

const rows = figure.find('tbody tr');
for (const row of rows) {
const code = parseRow(row);
if (code) yield code;
}
}
32 changes: 0 additions & 32 deletions get/src/source/orcicorn.ts

This file was deleted.

2 changes: 2 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -825,8 +825,10 @@ __metadata:
version: 0.0.0-use.local
resolution: "@shift-code/get@workspace:get"
dependencies:
"@types/cheerio": "npm:^0.22.35"
"@types/node": "npm:^22.18.6"
"@types/node-fetch": "npm:2.6.4"
cheerio: "npm:^1.1.2"
node-fetch: "npm:^2.7.0"
stream-json: "npm:^1.9.1"
typescript: "npm:^5.9.2"
Expand Down